diff options
-rw-r--r-- | TODO.rst | 8 | ||||
-rw-r--r-- | semantics.c | 26 | ||||
-rwxr-xr-x | test_all.sh | 5 | ||||
-rw-r--r-- | testcases/pass.c | 9 |
4 files changed, 40 insertions, 8 deletions
@@ -3,5 +3,9 @@ TODO - More detailed checking in regex for: - - char constant - - string constant + - char constant (done) + - string constant (done) + +- Fix: + + - local function declaration is not in a local scope diff --git a/semantics.c b/semantics.c index ed3cc47..00f956c 100644 --- a/semantics.c +++ b/semantics.c @@ -581,6 +581,11 @@ CTable_t semantics_fields(CNode *p, CScope_t scope) { CVar_t var = semantics_declr(declr, semantics_type_spec(p->chd, scope), scope, 0); + if (var->type->type == CFUNC) + { + sprintf(err_buff, "field '%s' declared as a function", var->name); + ERROR(var->ast); + } /* incomplete type checking */ if (!type_is_complete(var->type)) { @@ -794,6 +799,8 @@ ExpType exp_check_deref(ExpType op1, CNode *ast) { sprintf(err_buff, "invalid type argument of unary '*'"); ERROR(ast); } + if (op1.type->rec.ref->type == CFUNC) + return op1; op1.lval = 1; /* deref changes exp to lval */ if (!type_is_complete(op1.type = op1.type->rec.ref)) { @@ -805,6 +812,9 @@ ExpType exp_check_deref(ExpType op1, CNode *ast) { ExpType exp_check_ref(ExpType op1, CNode *ast) { ExpType res; + CType_t t = op1.type; + if (t->type == CARR || (t->type == CPTR && t->rec.ref->type == CFUNC)) + return op1; if (!op1.lval) { sprintf(err_buff, "lvalue required as unary '&' operand"); @@ -935,7 +945,8 @@ ExpType exp_check_postfix(CNode *p, CScope_t scope) { op1.lval = 1; break; case POSTFIX_CALL: - if (t1 != CFUNC) + if (!((t1 == CFUNC) || + (t1 == CPTR && op1.type->rec.ref->type == CFUNC))) { sprintf(err_buff, "called object is not a function"); ERROR(p); @@ -943,7 +954,10 @@ ExpType exp_check_postfix(CNode *p, CScope_t scope) { { CNode *arg = post->chd->chd; CType_t func = p->chd->ext.type; - CVar_t param = func->rec.func.params; + CVar_t param; + /* pointer to function */ + if (func->type == CPTR) func = func->rec.ref; + param = func->rec.func.params; for (; arg && param; arg = arg->next, param = param->next) { @@ -1026,6 +1040,12 @@ ExpType semantics_exp(CNode *p, CScope_t scope) { } res.type = p->ext.var->type; res.lval = !(res.type->type == CARR || res.type->type == CFUNC); + if (res.type->type == CFUNC) + { + CType_t f = ctype_create("", CPTR, p); + f->rec.ref = res.type; + res.type = f; + } break; case INT: res.type = basic_type_int; @@ -1325,7 +1345,7 @@ CVar_t semantics_func(CNode *p, CScope_t scope) { } scope->func = func; - cscope_enter(scope); /* enter function local scope */ + cscope_enter(scope); /* enter function local scope */ { /* Note: here is a dirty hack to forcibly push function definition to the global scope, while all the types specified in parameters retain in local scope. The key point is to make sure semantics_params does not push any var */ diff --git a/test_all.sh b/test_all.sh index 28c26d4..cb2aa87 100755 --- a/test_all.sh +++ b/test_all.sh @@ -1,11 +1,12 @@ #! /bin/bash -for file in test/* +for file in testcases/*.c do gcc $file -o /dev/null &> /dev/null gcc_ret="$?" ./cibic $file &> /dev/null if [ $? -ne $gcc_ret ]; then echo "Failed on $file" - break + else + echo "ok $file" fi done diff --git a/testcases/pass.c b/testcases/pass.c index 835483e..ebcae0a 100644 --- a/testcases/pass.c +++ b/testcases/pass.c @@ -72,7 +72,14 @@ void comma() { } int complex_pointer() { - int (*f(int ***e[10]))(); + int (*g(int ***e[10]))(); +} + +int fp(int a, int b, int c) { + int (*f)(int a, int b, int c); + f = ****fp + 1; + (****f)(1, 2, 3); + f = &fp + 1; } struct Node n; |