Commit 32077f8b authored by Sergio Costas's avatar Sergio Costas

Now doesn't fail when assigning to an element in a struct pointer

Now recognizes __builtin_swap16 and __builtin_clz

Now detects correctly when a function returns a pointer to void
parent 9ad1a498
......@@ -584,22 +584,29 @@ class crust(object):
dest_eval = self._eval_statement(statement.child1[0], thread_status, False)[0]
dest_var = dest_eval["node"]
dest_data = self._find_variable(thread_status, dest_var.name, statement.line)
if dest_var.right is not None:
if dest_var is None:
dest_data = None
dest_type = self.TYPE_NO_MATTER
else:
if dest_data["crust"] and (dest_data["function_params"] is None):
dest_type = self.TYPE_CRUST
dest_data = self._find_variable(thread_status, dest_var.name, statement.line)
if dest_var.right is not None:
dest_type = self.TYPE_NO_MATTER
else:
dest_type = self.TYPE_NO_CRUST
if dest_data["crust"] and (dest_data["function_params"] is None):
dest_type = self.TYPE_CRUST
else:
dest_type = self.TYPE_NO_CRUST
if dest_data["borrowed"] and (dest_var.right is None) and dest_data["is_parameter"]:
if (dest_data is not None) and dest_data["borrowed"] and (dest_var.right is None) and dest_data["is_parameter"]:
self._add_error(thread_status, self.MSG_ERROR, "Overwritting the borrowed argument '{:s}' at line {:d}", dest_data["name"], statement.line)
retvals = []
for orig_eval in threads:
dest_data = self._find_variable(orig_eval["thread_status"], dest_var.name, statement.line)
if dest_var is None:
dest_data = None
else:
dest_data = self._find_variable(orig_eval["thread_status"], dest_var.name, statement.line)
orig_type = orig_eval["type"]
orig_var = orig_eval["node"]
if orig_var is not None:
......@@ -658,10 +665,10 @@ class crust(object):
if dest_data["alias"]:
self._add_error(orig_eval["thread_status"], self.MSG_ERROR, "Assigning the crust-type result value of function '{:s}' to the alias '{:s}' at line {:d}", orig_data["name"], dest_data["name"], statement.line)
else:
if dest_data["borrowed"] and (dest_var.right is None) and dest_eval["pure"] and ((not orig_data["borrowed"]) or (orig_var.right is not None)):
if (dest_data is not None) and dest_data["borrowed"] and (dest_var.right is None) and dest_eval["pure"] and ((not orig_data["borrowed"]) or (orig_var.right is not None)):
self._add_error(thread_status, self.MSG_ERROR, "Assigning the non-borrowed block '{:s}' to the borrowed variable '{:s}' at line {:d}", orig_data["name"], dest_data["name"], statement.line)
if orig_data["borrowed"] and (orig_var.right is None):
if ((not dest_data["borrowed"]) or (dest_var.right is not None)) or (not dest_eval["pure"]):
if ((dest_data is not None) and ((not dest_data["borrowed"]) or (dest_var.right is not None))) or (not dest_eval["pure"]):
self._add_error(orig_eval["thread_status"], self.MSG_CRITICAL, "Assigning a borrowed block into a local variable is not allowed (assigning '{:s}' at line {:d})", orig_data["name"], statement.line)
if (orig_type == self.TYPE_CRUST) and (dest_type == self.TYPE_NO_CRUST):
self._add_error(orig_eval["thread_status"], 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)
......@@ -673,10 +680,10 @@ class crust(object):
self._add_error(orig_eval["thread_status"], 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) and (orig_eval["value"] != self.VALUE_NULL):
self._add_error(orig_eval["thread_status"], self.MSG_CRITICAL, "Assigning a non-crust value to the crust variable '{:s}' at line {:d}", dest_data["name"], statement.line)
if dest_data["borrowed"] and (dest_var.right is None) and (orig_eval["value"] != self.VALUE_NULL) and dest_eval["pure"]:
if (dest_var is not None) and (dest_data is not None) and dest_data["borrowed"] and (dest_var.right is None) and (orig_eval["value"] != self.VALUE_NULL) and dest_eval["pure"]:
self._add_error(thread_status, self.MSG_ERROR, "Assigning a value to the borrowed variable '{:s}' at line {:d}", dest_data["name"], statement.line)
if ((dest_var.right is not None) and (dest_data["pointer"] != 0)) or (not dest_eval["pure"]):
if ((dest_var is not None) and (dest_var.right is not None) and (dest_data["pointer"] != 0)) or (not dest_eval["pure"]):
if dest_data["value"] == self.VALUE_NULL:
self._add_error(orig_eval["thread_status"], self.MSG_ERROR, "Using variable '{:s}' at line {:d} with a NULL value", dest_data["name"], statement.line)
elif (dest_data["value"] == self.VALUE_NOT_NULL_OR_NULL) and (dest_data["crust"]) and (not dest_data["global"]):
......@@ -702,7 +709,7 @@ class crust(object):
old_block = self.id_counter
self.id_counter += 1
if (dest_var.right is None) and dest_eval["pure"]:
if (dest_var is not None) and (dest_var.right is None) and dest_eval["pure"]:
self._set_var_value(orig_eval["thread_status"], dest_var.name, orig_eval["value"], statement.line)
dest_data["uid"] = old_block
......@@ -1095,7 +1102,7 @@ class crust(object):
retval += self._eval_statement(statement.child2[0], thread["thread_status"], False)
return retval
print("statement type unknown '{:s}' at line {:d}".format(statement.type, statement.line))
print("statement type unknown '{:s}' at line {:d}, file {:s}".format(statement.type, statement.line, statement.filename))
return [ {"thread_status":thread_status, "value":self.VALUE_NOT_NULL_OR_NULL, "type":self.TYPE_NO_CRUST, "condition":self.CONDITION_FALSE_TRUE, "node":None, "pure": True} ]
......@@ -1270,12 +1277,14 @@ class crust(object):
""" Process the main tree with the global variables and the function definitions and declarations """
self.verbose = verbose
thread_status = { "variables": [ {} ], "debug_level": 0, "loop_level": 0, "find_label": None, "return_is_crust": False, "return_is_borrowed": False, "return_cant_null": False, "returned_something": None, "current_function": "", "filename": filename }
thread_status = { "variables": [ {} ], "debug_level": 0, "loop_level": 0, "find_label": None, "return_is_crust": None, "return_is_borrowed": False, "return_cant_null": False, "returned_something": None, "current_function": "", "filename": filename }
# Set the GCC builtin functions
self._add_builtin_function(thread_status, "__builtin_bswap16", "uint16_t", ["uint16_t"])
self._add_builtin_function(thread_status, "__builtin_bswap32", "uint32_t", ["uint32_t"])
self._add_builtin_function(thread_status, "__builtin_bswap64", "uint64_t", ["uint64_t"])
self._add_builtin_function(thread_status, "__builtin_clz", "int", ["unsigned int"])
# First fill all the global variables and the function declarations
for node in tree:
......@@ -1394,7 +1403,7 @@ class crust(object):
params["enum"] = False
tmpvars["variables"][0][parameter.name] = params
parameters = self._find_function(thread_status, node.name, -1)
if parameters[0]["void"]:
if parameters[0]["void"] and parameters[0]["pointer"] == 0:
tmpvars["return_is_crust"] = None
else:
tmpvars["return_is_crust"] = self._check_statement_is_crust(node, parameters[0])
......@@ -1667,7 +1676,7 @@ class crust(object):
if (thread["node"] is not None):
var_data = self._find_variable(tmp_status, thread["node"].name, node.line)
if var_data["value"] == self.VALUE_UNINITIALIZED:
self._add_error(tmp_status, self.MSG_ERROR, "Returning variable '{:s}' at line {:d} is uninitialized",thread["node"].name, node.line)
self._add_error(tmp_status, self.MSG_ERROR, "Returning variable '{:s}' at line {:d}, file '{:s}', is uninitialized",thread["node"].name, node.line, node.filename)
if (var_data["value"] == self.VALUE_FREED) or (var_data["value"] == self.VALUE_FREED_OR_NULL):
self._add_error(tmp_status, self.MSG_ERROR, "Returning variable '{:s}' at line {:d} was freed at line {:d}",thread["node"].name, node.line, var_data["init_line"])
if (self._check_statement_is_crust(thread["node"], var_data)) and (thread["type"] == self.TYPE_CRUST) and (not var_data["borrowed"]):
......@@ -1679,11 +1688,11 @@ class crust(object):
if tmp_status["returned_something"] == True:
if (thread["type"] == self.TYPE_CRUST) and (tmp_status["return_is_crust"] == False):
self._add_error(tmp_status, self.MSG_ERROR, "Return statement at line {:d} is returning a crust value, but is must return a non-crust one", node.line)
self._add_error(tmp_status, self.MSG_ERROR, "Return statement at line {:d}, file '{:s}', is returning a crust value, but is must return a non-crust one", node.line, node.filename)
if (thread["type"] != self.TYPE_CRUST) and (tmp_status["return_is_crust"] == True) and (thread["value"] != self.VALUE_NULL):
self._add_error(tmp_status, self.MSG_ERROR, "Return statement at line {:d} is returning a non-crust value, but is must return a crust one", node.line)
self._add_error(tmp_status, self.MSG_ERROR, "Return statement at line {:d}, file '{:s}', is returning a non-crust value, but is must return a crust one", node.line, node.filename)
if tmp_status["return_is_crust"] is None:
self._add_error(tmp_status, self.MSG_ERROR, "Return statement at line {:d} is returning a value, but the function '{:s}' does not return a value", node.line, tmp_status["current_function"])
self._add_error(tmp_status, self.MSG_ERROR, "Return statement at line {:d}, file '{:s}', is returning a value, but the function '{:s}' does not return a value", node.line, node.filename, tmp_status["current_function"])
if thread["node"] is None:
return_is_borrowed = False
else:
......@@ -1753,9 +1762,13 @@ class crust(object):
else:
init_loop = node.for_ch1
if node.for_ch2 is None:
init_loop = None
condition = None
else:
condition = node.for_ch2[0]
if (condition.type == "EMPTY_DECLARATOR"):
condition.type = "CONSTANT"
condition.intval = 1
condition.t_null = False
if node.for_ch3 is None:
end_loop = []
else:
......@@ -1885,7 +1898,6 @@ class crust(object):
else:
self._add_error(thread_status, self.MSG_CRITICAL, "Trying to set to NOT_NULL the state of the non-global variable '{:s}' at line {:d}", var_name, node.line)
return self._check_return_block(tree[1:], thread_status)
threads = self._eval_statement(node, thread_status, True)
retvals = []
for thread in threads:
......
......@@ -662,10 +662,10 @@ class Test(unittest.TestCase):
self._all_fine_test("unitest/test135.c")
def test136ReturnCrustExpectNoCrust(self):
self._generic_test("unitest/test136.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d} is returning a crust value, but is must return a non-crust one", 7) ])
self._generic_test("unitest/test136.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d}, file '{:s}', is returning a crust value, but is must return a non-crust one", 7, 'unitest/test136.c') ])
def test137ReturnNoCrustExpectCrust(self):
self._generic_test("unitest/test137.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d} is returning a non-crust value, but is must return a crust one", 7) ])
self._generic_test("unitest/test137.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d}, file '{:s}', is returning a non-crust value, but is must return a crust one", 7, 'unitest/test137.c') ])
def test138OddBreakInFor(self):
self._generic_test("unitest/test138.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param1", 7, 15) ])
......@@ -752,7 +752,7 @@ class Test(unittest.TestCase):
self._generic_test("unitest/test165.c", [ (crust.crust.MSG_ERROR, "Function '{:s}' expects a return value, but the code exited without it", "main") ])
def test166ExpectedNoReturnValueButValueAvailable(self):
self._generic_test("unitest/test166.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d} is returning a value, but the function '{:s}' does not return a value", 7, "main") ])
self._generic_test("unitest/test166.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d}, file '{:s}', is returning a value, but the function '{:s}' does not return a value", 7, 'unitest/test166.c', "main") ])
def test167ExpectedReturnValueEmptyReturn(self):
self._generic_test("unitest/test167.c", [ (crust.crust.MSG_ERROR, "Function '{:s}' expects a return value, but the code exited at line {:d} without it", "main", 9) ])
......@@ -764,7 +764,7 @@ class Test(unittest.TestCase):
self._generic_test("unitest/test169.c", [ (crust.crust.MSG_ERROR, "Returning variable '{:s}' at line {:d} was freed at line {:d}", "param", 7, 6) ])
def test170ReturnedUninitializedValue(self):
self._generic_test("unitest/test170.c", [ (crust.crust.MSG_ERROR, "Returning variable '{:s}' at line {:d} is uninitialized", "param", 5) ])
self._generic_test("unitest/test170.c", [ (crust.crust.MSG_ERROR, "Returning variable '{:s}' at line {:d}, file '{:s}', is uninitialized", "param", 5, 'unitest/test170.c') ])
def test171IgnoreBorrowReturnValue(self):
self._all_fine_test("unitest/test171.c")
......@@ -1001,6 +1001,9 @@ class Test(unittest.TestCase):
def test242CompareWithCrustPointerWithNullUninitialized(self):
self._generic_test("unitest/test242.c", [ (crust.crust.MSG_ERROR, "Using uninitialized variable '{:s}' at line {:d}", "p", 7) ])
def test243ReturnVoidPointer(self):
self._all_fine_test("unitest/test243.c")
if __name__ == '__main__':
try:
os.remove("error_list.txt")
......
void* function_name() {
return 0;
}
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