Commit 0f33a5ff authored by Sergio Costas's avatar Sergio Costas

Added full aliasing support

Added two unitary tests for aliasing support
parent 5dd00dfd
......@@ -93,6 +93,7 @@ class crusty(object):
self.errors = []
self.debug = []
self.print_debug = print_debug
self.uid_counter = 1
with open(headerpath,"r") as header:
do_process = False
......@@ -147,7 +148,7 @@ class crusty(object):
def _do_debug(self,var_container):
if self.print_debug:
print("Debug:")
for block in var_container:
for block in var_container["variables"]:
print(" Block:")
for variable in block:
print(" Variable: {:s}".format(variable))
......@@ -235,6 +236,21 @@ class crusty(object):
group = (err_type, err_value) + argv
if self.errors.count( group ) == 0:
self.errors.append( group )
# this line allows to detect formatting errors in the error messages in the line
# where they have been produced, and not at the end, when they will be printed
msg = _(err_value).format(*argv)
def _find_variable_by_id(self,var_container,var_id,line_number,searching_function = False):
""" Returns a variable using its unique id """
for var_group in var_container["variables"]:
for name in var_group:
if var_group[name]["uid"] == var_id:
return var_group[name]
if not searching_function:
self._add_error(var_container,self.MSG_CRITICAL,"Unknown variable ID '{:d}' at line {:d}",var_id,line_number)
raise self.VarNotFoundException()
def _find_variable(self,var_container,var_name,line_number,searching_function = False):
......@@ -268,7 +284,7 @@ class crusty(object):
self._add_error(var_container,self.MSG_CRITICAL,"Trying to assign a value to the function name '{:s}' at line {:d}",str(var_name),line_number)
return
if variable["alias"] and (variable["aliases"] is not None):
variable = variable["aliases"] # when modifying an alias, we really want to modify the original one
variable = self._find_variable_by_id(var_container,variable["aliases"],line_number) # when modifying an alias, we really want to modify the original one
if (not force) and variable["crust"]:
status = variable["status"]
if (status == crusty.STATUS_NOT_NULL) or (status == crusty.STATUS_NOT_NULL_OR_NULL):
......@@ -279,8 +295,9 @@ class crusty(object):
variable["status"] = value
if isinstance(variable["aliases"],list): # if this variable has aliases, we must update all of them
for element in variable["aliases"]:
element["status"] = value
element["init_line"] = variable["init_line"]
alias = self._find_variable_by_id(var_container,element,line_number)
alias["status"] = value
alias["init_line"] = variable["init_line"]
def _status_to_condition(self,retval):
......@@ -321,8 +338,8 @@ class crusty(object):
if var_crust is not None:
if var_crust["aliases"] is None:
var_crust["aliases"] = []
var_crust["aliases"].append(var_alias)
var_alias["aliases"] = var_crust
var_crust["aliases"].append(var_alias["uid"])
var_alias["aliases"] = var_crust["uid"]
var_alias["status"] = status
......@@ -669,6 +686,7 @@ class crusty(object):
""" Process a node that represents a variable or function definition, and returns a dictionary with its properties.
Properties:
name: the variable or function name
uid: unique number for aliases reference
crust: if TRUE, it is a crust_type variable
borrowed: if TRUE, it is a borrowed, crust_type function parameter
recycle: if TRUE, it is a recycle, crust_type function parameter
......@@ -686,10 +704,11 @@ class crusty(object):
array: TRUE if this variable is an array
function: TRUE if this is a function, or a pointer to a function. In the first case, status will be STATUS_FUNCTION
function_params: a list with the return values and the parameters of the function or function pointer, or None if this is not a function or function pointer
aliases: None if this function is not an alias or has no aliases. In case this variable HAS one or more aliases, this will be a list with all the dictionaries of this variable. If this variable IS an alias of other, this will be just the dictionary of that alias variable, or None if it hasn't been still assigned to a crust variable
aliases: None if this variable is not an alias or has no aliases. In case this variable HAS one or more aliases, this will be a list with all the UIDs of this variable. If this variable IS an alias of other, this will be just the UID of that alias variable, or None if it hasn't been still assigned to a crust variable
"""
retval = {"name": None, "crust": False, "borrowed": False, "recycle": False, "alias": False, "enum": False, "status": self.STATUS_UNINITIALIZED, "pointer": pointers, "struct": False, "array": False, "function": False, "function_params": None, "aliases": None }
retval = {"name": None, "uid": self.uid_counter, "crust": False, "borrowed": False, "recycle": False, "alias": False, "enum": False, "status": self.STATUS_UNINITIALIZED, "pointer": pointers, "struct": False, "array": False, "function": False, "function_params": None, "aliases": None }
self.uid_counter += 1
if not isinstance(node,self.AST_node):
return retval
......
......@@ -285,6 +285,12 @@ class Test(unittest.TestCase):
def testAssignmentToAndFromMemberOfBorrowBlock(self):
self._all_fine_test("unitest/test71.c")
def testAliasFreesBlock(self):
self._all_fine_test("unitest/test72.c")
def testAliasFreesBlock2(self):
self._generic_test("unitest/test73.c",[ (crusty.crusty.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} was freed at line {:d}",1,"main",10,9) ])
if __name__ == '__main__':
unittest.main()
typedef __crust_t__ int *crust_t;
#define NULL ((void *)0)
void main(crust_t param) {
crust_t __crust_alias__ an_alias = param;
__crust_debug__
main(an_alias); // this must work, and no error has to be emited because 'param' has been freed, because it is aliased by 'an_alias'
}
typedef __crust_t__ int *crust_t;
#define NULL ((void *)0)
void main(crust_t param) {
crust_t __crust_alias__ an_alias = param;
__crust_debug__
main(an_alias); // this must work, but now "param" must be marked as "free", so this code must not return an error
main(param); // ERROR: param has been freed when the alias "an_alias" has been used
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment