diff options
-rw-r--r-- | semantics.c | 59 | ||||
-rw-r--r-- | testcases/pass.c | 7 |
2 files changed, 52 insertions, 14 deletions
diff --git a/semantics.c b/semantics.c index ef2511c..6b14737 100644 --- a/semantics.c +++ b/semantics.c @@ -42,6 +42,7 @@ do { \ } while (0) #define IS_INT(tt) ((tt) == CINT || (tt) == CCHAR) +#define IS_PTR(tt) ((tt) == CPTR || (tt) == CARR) #define IS_ARITH(tt) IS_INT(tt) #define IS_SCALAR(tt) (!((tt) == CUNION || (tt) == CSTRUCT)) @@ -51,6 +52,9 @@ static char err_buff[MAX_ERROR_BUFF]; static CType_t basic_type_int; static CType_t basic_type_char; static CType_t basic_type_void; +static CVar_t builtin_printf; +static CVar_t builtin_scanf; +static CVar_t builtin_malloc; #ifdef CIBIC_DEBUG CTable_t ctable_create(Hashfunc_t hfunc, Printfunc_t pfunc) { @@ -688,8 +692,16 @@ void semantics_initr(CNode *p, CScope_t scope, CType_t type) { switch (p->rec.subtype) { case INITR_NORM: - exp_check_aseq_(type, semantics_exp(p->chd, scope).type, p); - break; + { + ExpType et = semantics_exp(p->chd, scope); + if (!scope->lvl && !p->chd->ext.is_const) /* in global scope */ + { + sprintf(err_buff, "initializer element is not constant"); + ERROR(p->chd); + } + exp_check_aseq_(type, et.type, p); + } + break; case INITR_ARR: { if (type->type == CARR) @@ -723,9 +735,6 @@ CVar_t semantics_decl(CNode *p, CScope_t scope) { { CNode *initr = p->chd->next; CVar_t var = semantics_declr(p->chd, type, scope, 0); - /* check initializer */ - if (initr->type == INITR) - semantics_initr(initr, scope, var->type); if (scope->lvl && !type_is_complete(var->type)) { sprintf(err_buff, "storage size of '%s' isn’t known", var->name); @@ -734,6 +743,9 @@ CVar_t semantics_decl(CNode *p, CScope_t scope) { var = var_merge(var, scope); var->next = res; res = var; + /* check initializer */ + if (initr->type == INITR) + semantics_initr(initr, scope, var->type); } useful = 1; } @@ -862,7 +874,7 @@ ExpType exp_check_add(ExpType op1, ExpType op2, CNode *p, char kind) { t2 = op2.type->type; NOT_IGNORE_VOID(op1.type, p); NOT_IGNORE_VOID(op2.type, p); - if (kind == '+' && t2 == CPTR) + if (kind == '+' && IS_PTR(t2)) { /* place the pointer type in the first place */ int t = t1; @@ -882,7 +894,7 @@ ExpType exp_check_add(ExpType op1, ExpType op2, CNode *p, char kind) { } if (kind == '-') { - if (t2 == CPTR && t1 != CPTR) + if (IS_PTR(t2) && !IS_PTR(t1)) { sprintf(err_buff, "invalid operands to binary operator"); ERROR(p); @@ -890,8 +902,7 @@ ExpType exp_check_add(ExpType op1, ExpType op2, CNode *p, char kind) { } else { - if (!((t1 == CINT || t1 == CCHAR || t1 == CPTR) && - (t2 == CINT || t2 == CCHAR))) + if (!((IS_INT(t1) || IS_PTR(t1)) && IS_INT(t2))) { sprintf(err_buff, "invalid operands to binary operator"); ERROR(p); @@ -902,7 +913,7 @@ ExpType exp_check_add(ExpType op1, ExpType op2, CNode *p, char kind) { int l = lch->ext.const_val, r = rch->ext.const_val, *a = &(p->ext.const_val); - if (t1 != CPTR && t2 != CPTR) + if (!IS_PTR(t1) && !IS_PTR(t2)) switch (kind) { case '+': *a = l + r; break; @@ -938,7 +949,7 @@ ExpType exp_check_scalar(ExpType op1, CNode *p) { } ExpType exp_check_deref(ExpType op1, CNode *p) { - if (op1.type->type != CPTR) + if (!IS_PTR(op1.type->type)) { sprintf(err_buff, "invalid type argument of unary '*'"); ERROR(p); @@ -1087,7 +1098,7 @@ ExpType exp_check_equality(ExpType op1, ExpType op2, CNode *p, int kind) { sprintf(err_buff, "invalid operands to binary operator"); ERROR(p); } - if (t1 == CPTR && t2 == CPTR) + if (IS_PTR(t1) && IS_PTR(t2)) { if (!is_same_type(op1.type->rec.ref, op2.type->rec.ref)) { @@ -1095,7 +1106,7 @@ ExpType exp_check_equality(ExpType op1, ExpType op2, CNode *p, int kind) { WARNING(p); } } - else if (t1 == CPTR || t2 == CPTR) + else if (IS_PTR(t1) || IS_PTR(t2)) { sprintf(err_buff, "comparison between pointer and integer"); WARNING(p); @@ -1110,7 +1121,7 @@ ExpType exp_check_postfix(CNode *p, CScope_t scope) { switch (post->rec.subtype) { case POSTFIX_ARR: - if (!(t1 == CARR || t1 == CPTR)) + if (!IS_PTR(t1)) { sprintf(err_buff, "subscripted value is neither array nor pointer"); ERROR(p); @@ -1600,15 +1611,35 @@ void semantics_check_(CNode *p, CScope_t scope) { } } +CVar_t make_builtin_func(const char *name, CType_t rt) { + CType_t func = ctype_create(name, CFUNC, NULL); + CVar_t res = cvar_create(name, func, NULL); + func->rec.func.params = NULL; + func->rec.func.body = NULL; + func->rec.func.local = NULL; + func->rec.func.ret = rt; + return res; +} + void semantics_check(CNode *p) { CScope_t scope = cscope_create(); basic_type_int = ctype_create("int", CINT, NULL); basic_type_char = ctype_create("char", CCHAR, NULL); basic_type_void = ctype_create("void", CVOID, NULL); + builtin_printf = make_builtin_func("printf", basic_type_int); + builtin_scanf = make_builtin_func("scanf", basic_type_int); + { + CType_t vstar = ctype_create("", CPTR, NULL); + vstar->rec.ref = basic_type_void; + builtin_malloc = make_builtin_func("malloc", vstar); + } /* add top-level basic types */ cscope_push_type(scope, basic_type_int); cscope_push_type(scope, basic_type_char); cscope_push_type(scope, basic_type_void); + cscope_push_var(scope, builtin_printf); + cscope_push_var(scope, builtin_scanf); + cscope_push_var(scope, builtin_malloc); /* check all definitions and declarations */ for (p = p->chd; p; p = p->next) { diff --git a/testcases/pass.c b/testcases/pass.c index cbd57b6..e489366 100644 --- a/testcases/pass.c +++ b/testcases/pass.c @@ -94,6 +94,13 @@ void array() { int a[(1 + 1 == 2) * 2]; } +void local_decl() { + int y = y; + { + int x = x; + } +} + struct Node n; struct Node {int x, y;} n; /* global forward declaration is ok */ |