Commit f535b08e authored by Sergio Costas's avatar Sergio Costas

Added support for function pointers

parent 1970e14f
......@@ -284,6 +284,8 @@ class crusty(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 value == self.STATUS_FREED:
return # never free a function pointer
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
......@@ -405,6 +407,13 @@ class crusty(object):
if assignment.type == "FUNCTION_CALL":
function_data = self._find_function(var_container,assignment.name,assignment.line)
function_status = self._find_variable(var_container,assignment.name,assignment.line)["status"]
if function_status == self.STATUS_NULL:
self._add_error(var_container,self.MSG_ERROR,"Using function pointer '{:s}' at line {:d} with NULL value",str(assignment.name),assignment.line)
elif function_status == self.STATUS_NOT_NULL_OR_NULL:
self._add_error(var_container,self.MSG_WARNING,"Using function pointer '{:s}' at line {:d} with a possible NULL value",str(assignment.name),assignment.line)
elif function_status == self.STATUS_UNINITIALIZED:
self._add_error(var_container,self.MSG_ERROR,"Using uninitialized function pointer '{:s}' at line {:d}",str(assignment.name),assignment.line)
if function_data[0]["crust"] and (function_data[0]["pointer"] == 1):
retval_type = self.TYPE_CRUST
else:
......@@ -768,11 +777,11 @@ class crusty(object):
def _node_fill_parameters(self,var_container,node,var_data):
if node.function_params is not None:
parameters = [ var_data.copy() ]
var_data["crust"] = False
for parameter in node.function_params:
if parameter.type != "EMPTY_DECLARATOR":
parameters.append( self._get_variable_properties(var_container,parameter,parameter.pointer,True) )
var_data["function_params"] = parameters
print(var_data)
return var_data
......
......@@ -96,11 +96,23 @@ postfix_expression
tmpleaf->child1 = $3;
free_tree($2);
free_tree($4); }
| postfix_expression '(' ')' { $$ = $1;
| postfix_expression '(' ')' { // calling a function without parameters
if (($1->type == '*') && ($1->child1 != NULL) && ($1->child1->type == IDENTIFIER)) {
$$ = $1->child1;
$1->child1 = NULL;
} else {
$$ = $1;
}
$$->type = FUNCTION_CALL;
free_tree($2);
free_tree($3); }
| postfix_expression '(' argument_expression_list ')' { $$ = $1;
| postfix_expression '(' argument_expression_list ')' { // calling a function with parameters
if (($1->type == '*') && ($1->child1 != NULL) && ($1->child1->type == IDENTIFIER)) {
$$ = $1->child1;
$1->child1 = NULL;
} else {
$$ = $1;
}
$$->type = FUNCTION_CALL;
$$->function_params = $3;
free_tree($2);
......@@ -516,7 +528,7 @@ direct_declarator
: IDENTIFIER { $$ = $1;
free($$->name);
$$->name = strdup($1->data); }
| '(' declarator ')' { $$ = $2;
| '(' declarator ')' { $$ = $2; // definition of a pointer to function
if ($$->pointer == 1) {
$$->function = true;
$$->pointer = 0;
......@@ -543,7 +555,7 @@ direct_declarator
append_right($$,tmpleaf);
free_tree($2);
free_tree($3); }
| direct_declarator '(' parameter_type_list ')' { $$ = $1;
| direct_declarator '(' parameter_type_list ')' { $$ = $1; // List of parameters in the definition of a function
$$->function_params = $3;
if (!$$->function) {
$$->type = FUNCTION_DECLARATION;
......@@ -551,7 +563,7 @@ direct_declarator
free_tree($2);
free_tree($4); }
| direct_declarator '(' identifier_list ')' { $$ = $1; show_error(__LINE__, $$); }
| direct_declarator '(' ')' { $$ = $1;
| direct_declarator '(' ')' { $$ = $1; // List of parameters in the definition of a function without parameters
if (!$$->function) {
$$->type = FUNCTION_DECLARATION;
}
......
......@@ -326,5 +326,27 @@ class Test(unittest.TestCase):
self._check_var_status(lib,"an_alias",crusty.crusty.STATUS_NOT_NULL_OR_NULL,0)
self._check_is_alias(lib,"an_alias",False,0)
def testFunctionPointerNull(self):
self._generic_test("unitest/test78.c",[ (crusty.crusty.MSG_ERROR,"Using function pointer '{:s}' at line {:d} with NULL value","test1",9) ])
def testFunctionPointerNull2(self):
self._generic_test("unitest/test79.c",[ (crusty.crusty.MSG_ERROR,"Using function pointer '{:s}' at line {:d} with NULL value","test1",7) ])
def testFunctionPointerFine(self):
self._all_fine_test("unitest/test80.c")
def testFunctionPointerFine2(self):
self._all_fine_test("unitest/test81.c")
def testFunctionPointerNonInitialized(self):
self._generic_test("unitest/test82.c",[ (crusty.crusty.MSG_ERROR,"Using uninitialized function pointer '{:s}' at line {:d}","test1",9) ])
def testFunctionPointerNonInitialized2(self):
self._generic_test("unitest/test83.c",[ (crusty.crusty.MSG_ERROR,"Using uninitialized function pointer '{:s}' at line {:d}","test1",7) ])
def testUndefinedPointerFunction(self):
self._raise_test("unitest/test84.c",crusty.crusty.FunctionNotFoundException, [ (crusty.crusty.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined","test1",6) ])
if __name__ == '__main__':
unittest.main()
typedef __crust_t__ unsigned char *crust_t;
typedef char* (*prueba)(crust_t);
#define NULL ((void *)0)
void main(crust_t param1) {
prueba test1 = NULL;
(*test1)(param1); // ERROR: calling a function pointer with a NULL value
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
void main(crust_t param1) {
char* (*test1)(crust_t) = NULL;
(*test1)(param1); // ERROR: calling a function pointer with a NULL value
}
typedef __crust_t__ unsigned char *crust_t;
typedef void (*prueba)(crust_t);
#define NULL ((void *)0)
void main(crust_t param1) {
prueba test1 = main;
(*test1)(param1); // all fine
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
void main(crust_t param1) {
void (*test1)(crust_t) = main;
(*test1)(param1); // all fine
}
typedef __crust_t__ unsigned char *crust_t;
typedef char* (*prueba)(crust_t);
#define NULL ((void *)0)
void main(crust_t param1) {
prueba test1;
(*test1)(param1); // ERROR: calling a function pointer without being initialized
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
void main(crust_t param1) {
char* (*test1)(crust_t);
(*test1)(param1); // ERROR: calling a function pointer without being initialized
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
void main(crust_t param1) {
(*test1)(param1); // ERROR: calling an undefined function pointer
}
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