From fe75fc6d0569f6df7ff33c96566873eb3ff10dc2 Mon Sep 17 00:00:00 2001 From: Teddy Date: Thu, 10 Apr 2014 16:30:04 +0800 Subject: fixed several bugs, see TODO --- TODO.rst | 14 ++++++------- semantics.c | 60 ++++++++++++++++++++++++++++++++++++++++---------------- testcases/pass.c | 4 ++++ 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/TODO.rst b/TODO.rst index 208fead..0b1d01c 100644 --- a/TODO.rst +++ b/TODO.rst @@ -11,15 +11,15 @@ TODO - check global definition (if type is complete) when semantic analysis finishes - local function declaration is not in a local scope (external linkage issue) - incomplete type issues - - function **definition** requires complete return type (function declaration does not) - - array requires **complete** elem type - - struct or union requires **complete** fields ( ``struct A;`` vs. ``struct A a;`` ?) - - pointer may **allow incomplete** type - - calculate type memory footprint when complete type is required - - function to 'pointer to function' conversion (according the std 6.3.2/4) + - function **definition** requires complete return type (function declaration does not) (done) + - array requires **complete** elem type (done) + - struct or union requires **complete** fields (done) + - pointer may **allow incomplete** type (done) + - calculate type memory footprint at proper time + - function to 'pointer to function' conversion (according the std 6.3.2/4) (done) - Not Implemented: - - complex type name (to be in agreement with complex decl) (almost done) + - complex type name (to be in agreement with complex decl) (almost done, need more tests) - initializer checking - typedef support (via adding mid-rule actions to bision to inform flex) diff --git a/semantics.c b/semantics.c index 2a3cfeb..4c87ebb 100644 --- a/semantics.c +++ b/semantics.c @@ -428,11 +428,25 @@ CType_t semantics_type_spec(CNode *p, CScope_t scope) { int type_is_complete(CType_t type) { switch(type->type) { - case CINT: case CCHAR: case CPTR: case CARR: + case CINT: case CCHAR: + /* basic types are always complete */ + case CPTR: + /* pointer may point to an incomplete type */ + case CARR: + /* syntax of incomplete arrays is not allowed in `cibic.y` */ return 1; case CSTRUCT: case CUNION: + /* fields are guaranteed to be complete if exists, due to + * `semantics_fields` */ return type->rec.fields != NULL; - default: ; /* TODO: CFUNC CVOID */ + case CVOID: + /* void type is never complete */ + return 0; + case CFUNC: + /* function body is not required here, it is checked in the last + * phase */ + return 1; + default: assert(0); } return 1; } @@ -451,6 +465,16 @@ CVar_t semantics_p_decl(CNode *p, CScope_t scope) { return var; } +/* pointer to function conversion (std 6.3.2/4) */ +#define FUNC_POINTER_CONV(t) \ + do { \ + if ((t)->type == CFUNC) \ + { \ + CType_t f = ctype_create("", CPTR, p); \ + f->rec.ref = t; \ + t = f; \ + } \ + } while (0) CVar_t semantics_params(CNode *p, CScope_t scope) { CHECK_TYPE(p, PARAMS); @@ -462,10 +486,12 @@ CVar_t semantics_params(CNode *p, CScope_t scope) { #else CTable_t tparams = ctable_create(bkdr_hash); #endif + FUNC_POINTER_CONV(params->type); ctable_insert(tparams, params->name, params, 0); for (p = p->next; p; p = p->next) { CVar_t var = semantics_p_decl(p, scope); + FUNC_POINTER_CONV(var->type); if (scope) /* params inside a function definition */ if (!ctable_insert(tparams, var->name, var, 0)) { @@ -505,7 +531,7 @@ CVar_t semantics_declr(CNode *p, CType_t type_spec, CScope_t scope, int func_chk cscope_exit(scope); /* incomplete type */ func->rec.func.local = NULL; - func->rec.func.ret = type_spec; + func->rec.func.ret = type_spec; /* might be an incomplete type */ func->rec.func.body = NULL; /* not a definition */ type = semantics_declr(p->chd, func, scope, 1); if (type_spec->type == CARR) @@ -525,6 +551,11 @@ CVar_t semantics_declr(CNode *p, CType_t type_spec, CScope_t scope, int func_chk case DECLR_ARR: { CType_t arr = ctype_create("", CARR, p); /* array declr */ + if (!type_is_complete(type_spec)) + { + sprintf(err_buff, "array type has incomplete element type"); + ERROR(p); + } arr->rec.arr.elem = type_spec; arr->rec.arr.len = p->chd->next->rec.intval; type = semantics_declr(p->chd, arr, scope, 0); @@ -556,15 +587,15 @@ 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) + /* types of fields are supposed to be complete */ + if (!type_is_complete(var->type)) { - sprintf(err_buff, "field '%s' declared as a function", var->name); + sprintf(err_buff, "field '%s' has incomplete type", var->name); ERROR(var->ast); } - /* incomplete type checking */ - if (!type_is_complete(var->type)) + if (var->type->type == CFUNC) { - sprintf(err_buff, "field '%s' has incomplete type", var->name); + sprintf(err_buff, "field '%s' declared as a function", var->name); ERROR(var->ast); } if (!ctable_insert(ct, var->name, var, 0)) @@ -946,8 +977,7 @@ ExpType exp_check_postfix(CNode *p, CScope_t scope) { op1.lval = 1; break; case POSTFIX_CALL: - if (!((t1 == CFUNC) || - (t1 == CPTR && op1.type->rec.ref->type == CFUNC))) + if (!(t1 == CPTR && op1.type->rec.ref->type == CFUNC)) { sprintf(err_buff, "called object is not a function"); ERROR(p); @@ -1041,12 +1071,7 @@ 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; - } + FUNC_POINTER_CONV(res.type); break; case INT: res.type = basic_type_int; @@ -1338,8 +1363,9 @@ CVar_t semantics_func(CNode *p, CScope_t scope) { scope, 0); CType_t func = head->type, funco; CVar_t res = cvar_create(head->name, func, p), old = NULL; + CType_t rt = func->rec.func.ret; - if (!type_is_complete(func->rec.func.ret)) + if (rt->type != CVOID && !type_is_complete(rt)) { sprintf(err_buff, "return type is an incomplete type"); ERROR(func->rec.func.ret->ast); diff --git a/testcases/pass.c b/testcases/pass.c index ebcae0a..4d9041e 100644 --- a/testcases/pass.c +++ b/testcases/pass.c @@ -82,6 +82,10 @@ int fp(int a, int b, int c) { f = &fp + 1; } +int f(int f()) { + f(complex_pointer); +} + struct Node n; struct Node {int x, y;} n; /* global forward declaration is ok */ -- cgit v1.2.3