Commit c1a7cbde authored by Sergio Costas's avatar Sergio Costas

Now checks if the return type is fine

parent 4f69efa4
......@@ -221,7 +221,7 @@ class crust(object):
def _copy_status(self, status):
""" Fully copies a thread_status to allow several parallel emulations """
retval = {"debug_level": status["debug_level"], "loop_level": status["loop_level"], "find_label": status["find_label"], "variables": []}
retval = {"debug_level": status["debug_level"], "loop_level": status["loop_level"], "find_label": status["find_label"], "return_is_crust": status["return_is_crust"], "variables": []}
for element in status["variables"]:
vargroup = {}
for varname in element:
......@@ -1026,7 +1026,7 @@ class crust(object):
def process_tree(self, tree):
""" Process the main tree with the global variables and the function definitions and declarations """
thread_status = { "variables": [ {} ], "debug_level": 0, "loop_level": 0, "find_label": None }
thread_status = { "variables": [ {} ], "debug_level": 0, "loop_level": 0, "find_label": None, "return_is_crust": False }
# First fill all the global variables and the function declarations
for node in tree:
if (node.type == "TYPE_SPECIFIER"):
......@@ -1090,17 +1090,13 @@ class crust(object):
params["init_line"] = element.line
params["enum"] = False
tmpvars["variables"][0][element.name] = params
parameters = self._find_function(thread_status, node.name, -1)
tmpvars["return_is_crust"] = self._check_statement_is_crust(node,parameters[0])
self._process_block(node.child1, tmpvars)
def _check_return_block(self, tree, thread_status):
if len(tree) == 0:
return [(None, thread_status)]
else:
return [(tree, thread_status)]
def _process_block(self, tree, thread_status):
thread_status["debug_level"] = 0
thread_status["loop_level"] = 0
thread_status["find_label"] = None
......@@ -1115,6 +1111,13 @@ class crust(object):
blocks += retval
def _check_return_block(self, tree, thread_status):
if len(tree) == 0:
return [(None, thread_status)]
else:
return [(tree, thread_status)]
def _print_tree(self, tree):
for node in tree:
print("{:s} at line {:d}".format(node.type, node.line))
......@@ -1232,12 +1235,26 @@ class crust(object):
if thread_status["find_label"] is None:
if node.type == "RETURN":
if node.child1 is not None:
self._eval_statement(node.child1[0], thread_status, True)
threads = self._eval_statement(node.child1[0], thread_status, True)
else:
threads = [ {"thread_status":thread_status, "value":self.VALUE_NOT_NULL_OR_NULL, "type":self.TYPE_NO_MATTER, "condition":self.CONDITION_FALSE_TRUE, "node":None} ]
# check if there are blocks in use
while(len(thread_status["variables"]) > 1):
self._check_blocks_in_use(thread_status, thread_status["variables"][0], node.line)
thread_status["variables"] = thread_status["variables"][1:]
return [(None, thread_status)]
retval = []
for thread in threads:
tmp_status = thread["thread_status"]
if (thread["node"] is not None):
var_data = self._find_variable(tmp_status,thread["node"].name,node.line)
if (self._check_statement_is_crust(thread["node"], var_data)) and (thread["type"] == self.TYPE_CRUST):
self._set_var_value(tmp_status, thread["node"].name, self.VALUE_FREED, node.line, True, True)
while(len(tmp_status["variables"]) > 1):
self._check_blocks_in_use(tmp_status, tmp_status["variables"][0], node.line)
tmp_status["variables"] = tmp_status["variables"][1:]
if (thread["type"] == self.TYPE_CRUST) and (not tmp_status["return_is_crust"]):
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)
if (thread["type"] != self.TYPE_CRUST) and (tmp_status["return_is_crust"]):
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)
retval.append( (None,thread) )
return retval
if node.type == "BREAK":
if thread_status["loop_level"] == 0:
......
......@@ -668,6 +668,18 @@ class Test(unittest.TestCase):
def test133GotoJumpsOverAll(self):
self._generic_test("unitest/test133.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 12, 21) ])
def test134ReturnCrustExpectCrust(self):
lib = self._all_fine_test("unitest/test134.c")
def test135ReturnNoCrustExpectNoCrust(self):
self._generic_test("unitest/test135.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 5, 7) ])
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) ])
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) ])
if __name__ == '__main__':
try:
os.remove("error_list.txt")
......
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
crust_t main(crust_t param) {
return param;
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
int main(crust_t param) {
return 0;
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
int main(crust_t param) {
return param;
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
crust_t main(int param) {
return param;
}
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