Commit 83f2a2f0 authored by Sergio Costas's avatar Sergio Costas

Now detects if a borroweb variable is passed as a non-borrow parameter

Extra checks
parent 4b4af148
......@@ -228,7 +228,7 @@ class crusty(object):
def _find_function(self,function_name,line_number):
if function_name in self._function_container:
return self._function_container[function_name]
self._add_error(self.MSG_CRITICAL,"Unknown function '{:s}' at line {:d}",str(function_name),line_number)
self._add_error(self.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined",function_name,line_number)
raise self.FunctionNotFoundException()
......@@ -363,9 +363,6 @@ class crusty(object):
return retvals
elif assignment.type == "FUNCTION_CALL":
if assignment.name not in self._function_container:
self._add_error(self.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined",assignment.name,assignment.line)
return [ (self.STATUS_NOT_NULL_OR_NULL, self._copy_container(var_container), self.TYPE_NO_MATTER, assignment.name) ]
function_data = self._find_function(assignment.name,assignment.line)
if ((function_data[0][0] & self.PROPERTY_CRUST_VARIABLE) != 0) and (function_data[0][1] == 1):
retval_type = self.TYPE_CRUST
......@@ -394,6 +391,7 @@ class crusty(object):
continue
assignment_var = self._find_variable(newvar_container,variable.name,assignment.line)
var_is_crusty = self._check_variable_properties(assignment_var,self.PROPERTY_CRUST_VARIABLE) and (assignment_var["pointer"] == 1)
var_is_borrow = self._check_variable_properties(assignment_var,self.PROPERTY_BORROWED)
if (not var_is_crusty) and param_is_crusty:
self._add_error(self.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed non __crust_t__ variable",pos+1,assignment.name,assignment.line)
......@@ -414,12 +412,14 @@ class crusty(object):
error_found = True
continue
if param_is_recycled:
if assignment_var["status"] == self.STATUS_NULL:
retval = self.STATUS_NOT_NULL_OR_NULL
if assignment_var["status"] == self.STATUS_NOT_NULL:
retval = self.STATUS_NOT_NULL
else:
retval = assignment_var["status"]
retval = self.STATUS_NOT_NULL_OR_NULL
if not param_is_borrowed:
self._set_var_value(newvar_container,variable.name,self.STATUS_FREED,assignment.line,True,True)
if var_is_borrow:
self._add_error(self.MSG_CRITICAL,"Parameter '{:s}' at position {:d} when calling function '{:s}' at line {:d} is borrowed, but is used as a non-borrow parameter",variable.name,pos+1,assignment.name,assignment.line)
if error_found:
return [ (self.STATUS_NOT_NULL_OR_NULL, newvar_container, retval_type, assignment.name) ]
return [ (retval, newvar_container, retval_type, assignment.name) ]
......@@ -630,6 +630,7 @@ class crusty(object):
return self._check_return_block(tree[1:],var_container)
if node.type == "CRUSTY_DEBUG":
print("Debug: '{:s}'".format(str(var_container)))
self.debug.append(self._copy_container(var_container))
return self._check_return_block(tree[1:],var_container)
if node.type == "START_BLOCK":
# append a new block for the variables created inside this block
......
......@@ -11,13 +11,24 @@ from crusty import crusty
class Test(unittest.TestCase):
def _find_variable(self,var_container,var_name):
for var_group in var_container:
if var_name in var_group:
return var_group[var_name]
return None
def _check_var_status(self,lib,variable,status):
var = self._find_variable(lib.debug[0],variable)
self.assertIsNot(var,None)
self.assertEqual(var["status"],status)
def _test_msg(self,lib,error_element,params):
self.assertEqual(len(error_element),len(params))
for index in range(len(error_element)):
self.assertEqual(error_element[index],params[index])
def _print_errors(self,filename,lib):
if True:
if False:
print("\rtest file: {:s}".format(filename))
lib.print_errors()
......@@ -31,6 +42,7 @@ class Test(unittest.TestCase):
self.assertEqual(len(lib.errors),len(params))
for i in range(len(lib.errors)):
self._test_msg(lib,lib.errors[i],params[i])
return lib
def _all_fine_test(self,filename):
......@@ -41,23 +53,27 @@ class Test(unittest.TestCase):
lib.process_functions(tree,variables)
self._print_errors(filename,lib)
self.assertEqual(len(lib.errors),0)
return lib
def testAllFine(self):
# This test just must work
self._all_fine_test("unitest/test1.c")
def testUnknownVariable(self):
# This test must fail with an Unknown variable exception and the corresponding error message
filename = "unitest/test2.c"
def _raise_test(self,filename,exception_class,params):
lib = crusty.crusty("lexyacclib/crusty.h","lexyacclib/crusty.so")
tree = lib.read_file(filename,False)
self.assertIsNot(tree,None)
variables = lib.process_tree(tree)
with self.assertRaises(crusty.crusty.VarNotFoundException):
with self.assertRaises(exception_class):
lib.process_functions(tree,variables)
self._print_errors(filename,lib)
self.assertEqual(len(lib.errors),1)
self._test_msg(lib,lib.errors[0], (crusty.crusty.MSG_CRITICAL,"Unknown variable '{:s}' at line {:d}", "var", 4) )
self.assertEqual(len(lib.errors),len(params))
for i in range(len(lib.errors)):
self._test_msg(lib,lib.errors[i],params[i])
return lib
def testAllFine(self):
# This test just must work
self._all_fine_test("unitest/test1.c")
def testUnknownVariable(self):
self._raise_test("unitest/test2.c",crusty.crusty.VarNotFoundException,[(crusty.crusty.MSG_CRITICAL,"Unknown variable '{:s}' at line {:d}", "var", 4)])
def testOverwrite(self):
self._generic_test("unitest/test3.c",[ (crusty.crusty.MSG_ERROR,"Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param3", 5, 4) ])
......@@ -81,7 +97,7 @@ class Test(unittest.TestCase):
self._generic_test("unitest/test9.c",[ (crusty.crusty.MSG_CRITICAL,"Calling function '{:s}' at line {:d} with an incorrect number of parameters","function",5) ])
def testNonExistingFunction(self):
self._generic_test("unitest/test10.c",[ (crusty.crusty.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined","function3",5) ])
self._raise_test("unitest/test10.c",crusty.crusty.FunctionNotFoundException, [ (crusty.crusty.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined","function3",5) ])
def testCrustParameterNotPointer(self):
self._generic_test("unitest/test11.c",[ (crusty.crusty.MSG_CRITICAL,"A parameter is defined as __crust_t__ type at line {:d}, but it is not a pointer",1) ])
......@@ -191,5 +207,23 @@ class Test(unittest.TestCase):
def testIfElseNull(self):
self._all_fine_test("unitest/test46.c")
def testRecycle(self):
lib = self._all_fine_test("unitest/test47.c")
self._check_var_status(lib,"var3",crusty.crusty.STATUS_NOT_NULL)
def testBorrow(self):
lib = self._all_fine_test("unitest/test48.c")
self._check_var_status(lib,"var2",crusty.crusty.STATUS_NOT_NULL)
def testBorrow2(self):
lib = self._all_fine_test("unitest/test49.c")
self._check_var_status(lib,"var2",crusty.crusty.STATUS_NULL)
def testPassBorrowToNonBorrow(self):
self._generic_test("unitest/test50.c",[ (crusty.crusty.MSG_CRITICAL,"Parameter '{:s}' at position {:d} when calling function '{:s}' at line {:d} is borrowed, but is used as a non-borrow parameter",'param',1,"test_function",9) ])
def testPassBorrowToBorrow(self):
self._all_fine_test("unitest/test51.c")
if __name__ == '__main__':
unittest.main()
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