Commit b15be6bf authored by Sergio Costas's avatar Sergio Costas

Added full support for overriding function signatures

parent aa2b6f61
......@@ -1294,20 +1294,26 @@ class crust(object):
tmpparams["ellipsis"] = node.t_ellipsis
tmpparams["definition_line"] = node.line
tmpparams["definition_file"] = node.filename
tmpparams["override"] = node.t_override
if node.name in thread_status["variables"][0]:
function_data = thread_status["variables"][0][node.name]
differ = False
if function_data["ellipsis"] != tmpparams["ellipsis"]:
differ = True
elif len(function_data["function_params"]) != len(tmpparams["function_params"]):
differ = True
if tmpparams["override"]:
del thread_status["variables"][0][node.name]
thread_status["variables"][0][node.name] = tmpparams
else:
for c in range(len(function_data["function_params"])):
if not self._compare_types(function_data["function_params"][c], tmpparams["function_params"][c], True):
if not function_data["override"]:
differ = False
if function_data["ellipsis"] != tmpparams["ellipsis"]:
differ = True
break
if differ:
self._add_error(thread_status, self.MSG_CRITICAL, "Function definition for '{:s}' at line {:d}, file '{:s}' differs from definition at line {:d}, file '{:s}'", node.name, node.line, node.filename, function_data["definition_line"], function_data["definition_file"])
elif len(function_data["function_params"]) != len(tmpparams["function_params"]):
differ = True
else:
for c in range(len(function_data["function_params"])):
if not self._compare_types(function_data["function_params"][c], tmpparams["function_params"][c], True):
differ = True
break
if differ:
self._add_error(thread_status, self.MSG_CRITICAL, "Function definition for '{:s}' at line {:d}, file '{:s}' differs from definition at line {:d}, file '{:s}'", node.name, node.line, node.filename, function_data["definition_line"], function_data["definition_file"])
else:
thread_status["variables"][0][node.name] = tmpparams
continue
......
......@@ -398,6 +398,9 @@ int prepare_leaf(unsigned long long int v1, double v2, int current_token) {
yylval->t_crust_not_null = true;
yylval->t_crust = true;
break;
case CRUST_OVERRIDE:
yylval->t_override = true;
break;
case T_NULL:
yylval->t_null = true;
free(yylval->data);
......
......@@ -378,7 +378,7 @@ declaration
;
override_declaration
: CRUST_OVERRIDE declaration { $$ = $2; $$->t_override = true; }
: CRUST_OVERRIDE declaration { $$ = $2; $$->t_override = true; }
declaration_specifiers
: storage_class_specifier { $$ = $1; show_debug(__LINE__, $$, "declaration_specifiers"); }
......@@ -883,7 +883,6 @@ block_item_list
block_item
: declaration { $$ = $1; show_debug(__LINE__, $$, "block_item"); }
| override_declaration { $$ = $1; show_debug(__LINE__, $$, "block_item"); }
| statement { $$ = $1; show_debug(__LINE__, $$, "block_item"); }
| CRUST_ENABLE { $$ = $1; show_debug(__LINE__, $$, "block_item"); }
| CRUST_DISABLE { $$ = $1; show_debug(__LINE__, $$, "block_item"); }
......@@ -1039,6 +1038,7 @@ translation_unit
external_declaration
: function_definition { $$ = $1; show_debug(__LINE__, $$, "external_declaration"); }
| declaration { $$ = $1; show_debug(__LINE__, $$, "external_declaration"); }
| override_declaration { $$ = $1; show_debug(__LINE__, $$, "external_declaration"); }
;
function_definition
......
......@@ -940,6 +940,17 @@ class Test(unittest.TestCase):
def test222TestConditionTrue(self):
self._generic_test("unitest/test222.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "var", 11, 21) ])
def test223TestOverrideSignature(self):
self._all_fine_test("unitest/test223.c")
def test224TestOverrideSignature2(self):
self._all_fine_test("unitest/test224.c")
def test225TestNotOverrideSignature(self):
self._generic_test("unitest/test225.c", [ (crust.crust.MSG_CRITICAL, "Function definition for '{:s}' at line {:d}, file '{:s}' differs from definition at line {:d}, file '{:s}'", "test_function", 4, "unitest/test225.c", 3, "unitest/test225.c"), (crust.crust.MSG_CRITICAL, "Expected a non __crust__ variable as argument {:d} when calling function '{:s}' at line {:d}, but passed a __crust__ variable", 1, "test_function", 9) ])
def test226TestNotOverrideSignature2(self):
self._generic_test("unitest/test226.c", [ (crust.crust.MSG_CRITICAL, "Function definition for '{:s}' at line {:d}, file '{:s}' differs from definition at line {:d}, file '{:s}'", "test_function", 4, "unitest/test226.c", 3, "unitest/test226.c") ])
if __name__ == '__main__':
try:
......
typedef __crust__ unsigned char *crust_t;
__crust_override__ void test_function(crust_t __crust_borrow__ param);
void test_function(unsigned char *param); // this one must be ignored
#define NULL ((void *)0)
void main(crust_t __crust_borrow__ param) {
test_function(param);
}
typedef __crust__ unsigned char *crust_t;
void test_function(unsigned char *param); // this one must be ignored
__crust_override__ void test_function(crust_t __crust_borrow__ param);
#define NULL ((void *)0)
void main(crust_t __crust_borrow__ param) {
test_function(param);
}
typedef __crust__ unsigned char *crust_t;
void test_function(unsigned char *param);
void test_function(crust_t __crust_borrow__ param); // this one must fail
#define NULL ((void *)0)
void main(crust_t __crust_borrow__ param) {
test_function(param); // this one must also fail
}
typedef __crust__ unsigned char *crust_t;
void test_function(crust_t __crust_borrow__ param);
void test_function(unsigned char *param); // this one must fail
#define NULL ((void *)0)
void main(crust_t __crust_borrow__ param) {
test_function(param); // this one must not fail
}
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