Commit 3aae8dc7 authored by Sergio Costas's avatar Sergio Costas

Much more clear code for assigning the final value

Added more tests for aliases
parent 36b2fdcb
......@@ -290,7 +290,7 @@ class crust(object):
def _set_var_value(self, var_container, var_name, value, line_number, force = False, force_init_line = False, to_alias = False):
def _set_var_value(self, var_container, var_name, value, line_number, force = False, force_init_line = False):
""" Set the new status of a variable """
variable = self._find_variable(var_container, var_name, line_number)
......@@ -300,13 +300,8 @@ class crust(object):
if variable["pointer"] == 0:
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"]:
if to_alias:
if variable["aliases"] is not None: # we are assigning a value to an alias, so we must remove this alias from the base variable
self._remove_alias(var_container, variable)
else:
if (variable["aliases"] is not None):
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 variable["alias"] and (variable["aliases"] is not None):
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 == crust.STATUS_NOT_NULL) or (status == crust.STATUS_NOT_NULL_OR_NULL):
......@@ -360,10 +355,11 @@ class crust(object):
else:
base_alias["aliases"] = new_aliases
var_alias["aliases"] = None
self._set_var_value(var_container, var_alias["name"], self.STATUS_UNINITIALIZED, -1, True)
def _assign_alias(self, var_container, data_alias, var_crust, status):
""" Assing a crust variable to an alias variable and update the alias status """
def _assign_alias(self, var_container, data_alias, var_crust):
""" Assing a crust variable to an alias variable """
self._remove_alias(var_container, data_alias)
......@@ -376,7 +372,6 @@ class crust(object):
data_crust["aliases"] = []
data_crust["aliases"].append(data_alias["uid"])
data_alias["aliases"] = data_crust["uid"]
data_alias["status"] = status
def _check_statement_is_crust(self, statement, vardata = None):
......@@ -386,6 +381,9 @@ class crust(object):
vars -- the variable's dictionary to check, or None if no dictionary is available, or only the statement data must be used
"""
if statement is None:
return False
if vardata is None:
if statement.t_crust and (statement.pointer == 1) and (statement.right is None):
return True
......@@ -512,8 +510,8 @@ class crust(object):
dest_data = self._find_variable(v["varlist"], dest_var.name, statement.line)
dest_status = dest_data["status"]
orig_type = v["type"]
if v["node"] is not None:
orig_var = v["node"]
orig_var = v["node"]
if orig_var is not None:
orig_data = self._find_variable(v["varlist"], orig_var.name, orig_var.line)
if orig_data["function"]:
if orig_var.function_params is None:
......@@ -546,9 +544,6 @@ class crust(object):
self._add_error(v["varlist"], self.MSG_ERROR, "Assigning the crust-type result value of function '{:s}' at line {:d} to the non-crust variable '{:s}'", orig_data["name"], statement.line, statement.name)
if (not ret_value["crust"]) and (dest_type == self.TYPE_CRUST):
self._add_error(v["varlist"], self.MSG_ERROR, "Assigning the non-crust-type result value of function '{:s}' at line {:d} to the crust variable '{:s}'", orig_data["name"], statement.line, statement.name)
if dest_data["alias"]:
self._remove_alias(v["varlist"], dest_data)
self._set_var_value(v["varlist"], dest_var.name, v["status"], statement.line, False, False, True)
else:
if orig_data["borrowed"] and (orig_var.right is None):
self._add_error(var_container, self.MSG_ERROR, "Assigning a borrowed block into a local variable is not allowed (assigning '{:s}' at line {:d})", orig_data["name"], statement.line)
......@@ -556,23 +551,25 @@ class crust(object):
self._add_error(v["varlist"], self.MSG_CRITICAL, "Assigning the crust variable '{:s}' to the non-crust variable '{:s}' at line {:d}", orig_var.name, dest_data["name"], statement.line)
if (orig_type == self.TYPE_NO_CRUST) and (dest_type == self.TYPE_CRUST):
self._add_error(v["varlist"], self.MSG_CRITICAL, "Assigning the non-crust variable '{:s}' to the crust variable '{:s}' at line {:d}", orig_var.name, dest_data["name"], statement.line)
if dest_data["alias"] and (dest_var.right is None):
self._assign_alias(v["varlist"], dest_data, orig_var, v["status"])
else:
if (orig_type == self.TYPE_CRUST) and self._check_statement_is_crust(orig_var, orig_data):
# only check and modify if the origin variable IS really a crust one, and is being managed as a crust one
self._check_can_be_used(v["varlist"], orig_var, statement.line)
self._set_var_value(v["varlist"], orig_var.name, self.STATUS_FREED, statement.line, True, True)
else:
orig_data = None
if (orig_type == self.TYPE_CRUST) and (dest_type == self.TYPE_NO_CRUST):
self._add_error(v["varlist"], self.MSG_CRITICAL, "Assigning a crust pointer to the non-crust variable '{:s}' at line {:d}", dest_data["name"], statement.line)
if (orig_type == self.TYPE_NO_CRUST) and (dest_type == self.TYPE_CRUST):
self._add_error(v["varlist"], self.MSG_CRITICAL, "Assigning a non-crust value to the crust variable '{:s}' at line {:d}", dest_data["name"], statement.line)
if (orig_type == self.TYPE_CRUST) and self._check_statement_is_crust(orig_var, orig_data):
# only check and modify if the origin variable IS really a crust one, and is being managed as a crust one
self._check_can_be_used(v["varlist"], orig_var, statement.line)
self._set_var_value(v["varlist"], orig_var.name, self.STATUS_FREED, statement.line, True, True)
if (dest_var.right is None):
if dest_data["alias"]:
self._remove_alias(v["varlist"], dest_data)
self._set_var_value(v["varlist"], dest_var.name, v["status"], statement.line, False, False, True)
if (dest_var.right is None) and (not dest_data["alias"]):
if (orig_data is not None) and (orig_var.right is None) and (not orig_data["function"]):
self._assign_alias(v["varlist"], dest_data, orig_var)
self._set_var_value(v["varlist"], dest_var.name, v["status"], statement.line)
retvals.append( { "varlist":v["varlist"], "status":v["status"], "type":dest_type, "condition":self._status_to_condition(v["status"]), "node":dest_var} )
return retvals
......@@ -948,9 +945,10 @@ class crust(object):
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 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
ellipsis: if it is a function definition, this field will be TRUE if the parameter list end with ellipsis (...) to specify a function with a variable number of parameters
init_line: the line in which this variable was first initialized
"""
retval = {"name": None, "uid": self.uid_counter, "crust": False, "borrowed": False, "recycle": False, "alias": False, "void": False, "enum": False, "status": self.STATUS_UNINITIALIZED, "pointer": pointers, "struct": False, "array": False, "function": False, "function_params": None, "aliases": None, "ellipsis": False }
retval = {"name": None, "uid": self.uid_counter, "crust": False, "borrowed": False, "recycle": False, "alias": False, "void": False, "enum": False, "status": self.STATUS_UNINITIALIZED, "pointer": pointers, "struct": False, "array": False, "function": False, "function_params": None, "aliases": None, "ellipsis": False, "init_line": -1 }
self.uid_counter += 1
if not isinstance(node, self.AST_node):
return retval
......
......@@ -42,7 +42,7 @@ class Test(unittest.TestCase):
parent = self._find_variable(lib.debug[deep], parent)
self.assertIsNot(var, None)
self.assertIsNotNone(var["aliases"])
self.assertEqual(var["aliases"],parent["uid"])
self.assertEqual(var["aliases"], parent["uid"])
self.assertTrue(0 != parent["aliases"].count(var["uid"]))
def _test_msg(self, lib, error_element, params):
......@@ -348,9 +348,9 @@ class Test(unittest.TestCase):
def test077DecoupleAlias3(self):
lib = self._all_fine_test("unitest/test77.c")
self._check_var_status(lib, "param", crust.crust.STATUS_FREED, 0)
self._check_var_status(lib, "an_alias", crust.crust.STATUS_NOT_NULL_OR_NULL, 0)
self._check_is_alias(lib, "an_alias", False, 0)
self._check_var_status(lib, "param", crust.crust.STATUS_FREED, 1)
self._check_var_status(lib, "an_alias", crust.crust.STATUS_NOT_NULL_OR_NULL, 1)
self._check_is_alias(lib, "an_alias", False, 1)
def test078FunctionPointerNull(self):
self._generic_test("unitest/test78.c", [ (crust.crust.MSG_ERROR, "Using function pointer '{:s}' at line {:d} with NULL value", "test1", 9) ])
......@@ -600,6 +600,71 @@ class Test(unittest.TestCase):
self._check_is_alias(lib, "alias2", True, 4)
self._check_is_alias_of(lib, "alias2", "param", 4)
def test131AssignAliasFromAlias(self):
lib = self._all_fine_test("unitest/test131.c")
self._check_var_status(lib, "param", crust.crust.STATUS_NOT_NULL_OR_NULL, 0)
self._check_var_status(lib, "alias1", crust.crust.STATUS_UNINITIALIZED, 0)
self._check_var_status(lib, "alias2", crust.crust.STATUS_UNINITIALIZED, 0)
self._check_is_alias(lib, "alias1", False, 0)
self._check_is_alias(lib, "alias2", False, 0)
self._check_var_status(lib, "param", crust.crust.STATUS_NOT_NULL_OR_NULL, 1)
self._check_var_status(lib, "alias1", crust.crust.STATUS_NOT_NULL_OR_NULL, 1)
self._check_var_status(lib, "alias2", crust.crust.STATUS_UNINITIALIZED, 1)
self._check_is_alias(lib, "alias1", True, 1)
self._check_is_alias(lib, "alias2", False, 1)
self._check_is_alias_of(lib, "alias1", "param", 1)
self._check_var_status(lib, "param", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_var_status(lib, "alias1", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_var_status(lib, "alias2", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_is_alias(lib, "alias1", True, 2)
self._check_is_alias(lib, "alias2", True, 2)
self._check_is_alias_of(lib, "alias1", "param", 2)
self._check_is_alias_of(lib, "alias2", "param", 2)
self._check_var_status(lib, "param", crust.crust.STATUS_FREED, 3)
self._check_var_status(lib, "alias1", crust.crust.STATUS_FREED, 3)
self._check_var_status(lib, "alias2", crust.crust.STATUS_FREED, 3)
self._check_is_alias(lib, "alias1", True, 3)
self._check_is_alias(lib, "alias2", True, 3)
self._check_is_alias_of(lib, "alias2", "param", 3)
def test132AssignAliasFromAlias(self):
lib = self._all_fine_test("unitest/test132.c")
self._check_var_status(lib, "param1", crust.crust.STATUS_NOT_NULL_OR_NULL, 0)
self._check_var_status(lib, "param2", crust.crust.STATUS_NOT_NULL_OR_NULL, 0)
self._check_var_status(lib, "alias1", crust.crust.STATUS_UNINITIALIZED, 0)
self._check_var_status(lib, "alias2", crust.crust.STATUS_UNINITIALIZED, 0)
self._check_is_alias(lib, "alias1", False, 0)
self._check_is_alias(lib, "alias2", False, 0)
self._check_var_status(lib, "param1", crust.crust.STATUS_NOT_NULL_OR_NULL, 1)
self._check_var_status(lib, "param2", crust.crust.STATUS_NOT_NULL_OR_NULL, 1)
self._check_var_status(lib, "alias1", crust.crust.STATUS_NOT_NULL_OR_NULL, 1)
self._check_var_status(lib, "alias2", crust.crust.STATUS_UNINITIALIZED, 1)
self._check_is_alias(lib, "alias1", True, 1)
self._check_is_alias(lib, "alias2", False, 1)
self._check_is_alias_of(lib, "alias1", "param1", 1)
self._check_var_status(lib, "param1", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_var_status(lib, "param2", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_var_status(lib, "alias1", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_var_status(lib, "alias2", crust.crust.STATUS_NOT_NULL_OR_NULL, 2)
self._check_is_alias(lib, "alias1", True, 2)
self._check_is_alias(lib, "alias2", True, 2)
self._check_is_alias_of(lib, "alias1", "param1", 2)
self._check_is_alias_of(lib, "alias2", "param2", 2)
self._check_var_status(lib, "param1", crust.crust.STATUS_FREED, 3)
self._check_var_status(lib, "param2", crust.crust.STATUS_NOT_NULL_OR_NULL, 3)
self._check_var_status(lib, "alias1", crust.crust.STATUS_FREED, 3)
self._check_var_status(lib, "alias2", crust.crust.STATUS_NOT_NULL_OR_NULL, 3)
self._check_is_alias(lib, "alias1", True, 3)
self._check_is_alias(lib, "alias2", True, 3)
self._check_is_alias_of(lib, "alias1", "param1", 3)
self._check_is_alias_of(lib, "alias2", "param2", 3)
if __name__ == '__main__':
try:
os.remove("error_list.txt")
......
......@@ -7,7 +7,7 @@ crust_t function(crust_t param);
void main(crust_t param) {
crust_t __crust_alias__ an_alias = param;
__crust_debug__
an_alias = function(param); // this must work, and 'an_alias' must be NULL_OR_NOT_NULL, and NOT be an alias of param
__crust_debug__
}
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