From f446f65340d41d6b4558a26912ba15e28059fe48 Mon Sep 17 00:00:00 2001 From: Teddy Date: Sun, 6 Apr 2014 10:26:37 +0800 Subject: complex cast almost done --- TODO.rst | 3 ++- ast.c | 2 +- ast.h | 1 - cibic.y | 35 ++++++++++++++++++++++++++++++++--- semantics.c | 47 +++++++++++++++++++++-------------------------- testcases/cast.c | 3 +++ testcases/cast2.c | 3 +++ testcases/cast3.c | 3 +++ testcases/fail10.c | 4 ++++ testcases/fail11.c | 4 ++++ testcases/fail8.c | 5 +++++ testcases/localfunc.c | 4 ++++ 12 files changed, 82 insertions(+), 32 deletions(-) create mode 100644 testcases/cast.c create mode 100644 testcases/cast2.c create mode 100644 testcases/cast3.c create mode 100644 testcases/fail10.c create mode 100644 testcases/fail11.c create mode 100644 testcases/fail8.c create mode 100644 testcases/localfunc.c diff --git a/TODO.rst b/TODO.rst index e2fbcc6..d896657 100644 --- a/TODO.rst +++ b/TODO.rst @@ -12,4 +12,5 @@ TODO - Not Implemented: - - Complex type name (to be in agreement with complex decl) + - complex type name (to be in agreement with complex decl) (almost done) + - initializer checking diff --git a/ast.c b/ast.c index 1b0d3b5..44952d8 100644 --- a/ast.c +++ b/ast.c @@ -231,7 +231,6 @@ char *cnode_debug_type_repr(CNode *ast) { case DECL: type = "decl"; break; case INIT_DECLR: type = "init_declr"; break; case PLAIN_DECL: type = "p_decl"; break; - case TYPE_NAME: type = "type_name"; break; case COMP_STMTS: type = "blk_stmts"; break; case COMP_DECLS: type = "blk_decls"; break; case DECLRS: type = "declrs"; break; @@ -331,6 +330,7 @@ char *cnode_debug_type_repr(CNode *ast) { case DECLR_FUNC: type = "func"; break; case DECLR_ARR: type = "arr"; break; case '*': type = "*"; break; + case 0: type = "typename"; break; default: assert(0); } } diff --git a/ast.h b/ast.h index 016b09b..c12e2b9 100644 --- a/ast.h +++ b/ast.h @@ -28,7 +28,6 @@ typedef struct CNode { /* Expressions */ EXP, - TYPE_NAME, ID, /* identifier */ INT, /* INT_CONST */ CHAR, diff --git a/cibic.y b/cibic.y index 5d707b7..c4e45e2 100644 --- a/cibic.y +++ b/cibic.y @@ -19,7 +19,7 @@ %type INT_CONST %type IDENTIFIER STR_CONST CHAR_CONST %type additive_operator assignment_operator equality_operator multiplicative_operator relational_operator shift_operator struct_or_union unary_operator -%type additive_expression and_expression arguments array_initializer assignment_expression cast_expression comp_decls compound_statement comp_stmts constant_expression declaration declarator declarators equality_expression exclusive_or_expression expression expression_statement function_definition identifier inclusive_or_expression init_declarator init_declarators initializer iteration_statement jump_statement logical_and_expression logical_or_expression multiplicative_expression optional_exp parameters plain_declaration direct_declarator postfix postfix_expression primary_expression prog_list program relational_expression selection_statement shift_expression statement struct_field struct_fields type_name type_specifier unary_expression +%type additive_expression and_expression arguments array_initializer assignment_expression cast_expression comp_decls compound_statement comp_stmts constant_expression declaration declarator declarators equality_expression exclusive_or_expression expression expression_statement function_definition identifier inclusive_or_expression init_declarator init_declarators initializer iteration_statement jump_statement logical_and_expression logical_or_expression multiplicative_expression optional_exp parameters plain_declaration direct_declarator postfix postfix_expression primary_expression prog_list program relational_expression selection_statement shift_expression statement struct_field struct_fields type_name type_specifier unary_expression abstract_declarator direct_abstract_declarator direct_abstract_declarator_opt abstract_declarator_opt %start program %% program @@ -290,8 +290,37 @@ cast_expression $$ = cnode_add_loc(cnode_create_exp(EXP_CAST, 2, $2, $4), @$); } type_name - : type_specifier - | type_name '*' { $$ = cnode_add_loc(cnode_create_exp('*', 1, $1), @$); } + : type_specifier abstract_declarator_opt { + $$ = cnode_add_loc(cnode_create_declr(0, 2, $1, $2), @$); } + +abstract_declarator_opt + : { $$ = cnode_create_nop(); } + | abstract_declarator + +abstract_declarator + : '*' { $$ = cnode_add_loc(cnode_create_declr('*', 1, cnode_create_nop()), @$); } + | '*' abstract_declarator { $$ = cnode_add_loc(cnode_create_declr('*', 1, $2), @$); } + | direct_abstract_declarator + +direct_abstract_declarator_opt + : { $$ = cnode_create_nop(); } + | direct_abstract_declarator + +direct_abstract_declarator + : '(' abstract_declarator ')' { $$ = $2; } + | direct_abstract_declarator '(' parameters ')' { + $$ = cnode_add_loc(cnode_create_declr( + DECLR_FUNC, 2, $1, + cnode_add_loc(cnode_list_wrap(PARAMS, $3), @3)), @$); + } + | '(' parameters ')' { + $$ = cnode_add_loc(cnode_create_declr( + DECLR_FUNC, 2, cnode_create_nop(), + cnode_add_loc(cnode_list_wrap(PARAMS, $2), @2)), @$); + } + | direct_abstract_declarator_opt '[' constant_expression ']' { + $$ = cnode_add_loc(cnode_create_declr(DECLR_ARR, 2, $1, $3), @$); + } unary_expression : postfix_expression diff --git a/semantics.c b/semantics.c index 68884ce..39ca0c1 100644 --- a/semantics.c +++ b/semantics.c @@ -493,7 +493,8 @@ CVar_t semantics_declr(CNode *p, CType_t type_spec, CScope_t scope, int func_chk if (!func_chk) CHECK_CVOID(p->rec.strval, p); return cvar_create(p->rec.strval, type_spec, p); } - + if (p->type == NOP) /* type name */ + return cvar_create(NULL, type_spec, p); switch (p->rec.subtype) { case DECLR_FUNC: @@ -681,37 +682,30 @@ ExpType exp_check_aseq(ExpType lhs, ExpType rhs, CNode *ast) { #define IS_INT(tt) ((tt) == CINT || (tt) == CCHAR) #define IS_ARITH(tt) IS_INT(tt) -#define IS_SCALAR(tt) (IS_ARITH(tt) || (tt) == CPTR || (tt) == CARR) +#define IS_SCALAR(tt) (!((tt) == CUNION || (tt) == CSTRUCT)) -CType_t semantics_cast(CNode *p, CScope_t scope) { - CNode *t, *ast; - CType_t tt, type; - if (p->type == TYPE_SPEC) +CType_t semantics_typename(CNode *p, CScope_t scope) { + CVar_t var = semantics_declr(p->chd->next, + semantics_type_spec(p->chd, scope), + scope, 0); + CType_t type = var->type; + free(var); + if (!IS_SCALAR(type->type)) { - type = semantics_type_spec(p, scope); - ast = p; + sprintf(err_buff, "conversion to non-scalar type requested"); + ERROR(p); } - else + if (type->type == CARR) { - type = ctype_create("", CPTR, p); /* pointer */ - for (t = p, tt = type;; t = t->chd) - { - if (t->chd->type == TYPE_SPEC) - { - tt->rec.ref = semantics_type_spec(t->chd, scope); - ast = t; - break; - } - tt->rec.ref = ctype_create("", CPTR, t); - tt = tt->rec.ref; - } + sprintf(err_buff, "cast specifies array type"); + ERROR(p); } - if (!IS_SCALAR(type->type)) + if (type->type == CFUNC) { - sprintf(err_buff, "conversion to non-scalar type requested"); - ERROR(ast); + sprintf(err_buff, "cast specifies function type"); + ERROR(p); } - type->ast = ast; + type->ast = p; return type; } @@ -1121,7 +1115,7 @@ ExpType semantics_exp(CNode *p, CScope_t scope) { res = exp_check_arith(op1, op2, p); break; case EXP_CAST: - res.type = semantics_cast(p->chd, scope); + res.type = semantics_typename(p->chd, scope); res.lval = 0; break; case '&': @@ -1395,6 +1389,7 @@ CVar_t semantics_func(CNode *p, CScope_t scope) { funco->rec.func.body = res->type->rec.func.body; free(res); } + free(head); return old; } diff --git a/testcases/cast.c b/testcases/cast.c new file mode 100644 index 0000000..b441552 --- /dev/null +++ b/testcases/cast.c @@ -0,0 +1,3 @@ +int main() { + ((int (*)(int a))1)(1); +} diff --git a/testcases/cast2.c b/testcases/cast2.c new file mode 100644 index 0000000..34b3484 --- /dev/null +++ b/testcases/cast2.c @@ -0,0 +1,3 @@ +int main() { + (int [3])1; +} diff --git a/testcases/cast3.c b/testcases/cast3.c new file mode 100644 index 0000000..4500cb1 --- /dev/null +++ b/testcases/cast3.c @@ -0,0 +1,3 @@ +int main() { + (int ())1; +} diff --git a/testcases/fail10.c b/testcases/fail10.c new file mode 100644 index 0000000..e287c6f --- /dev/null +++ b/testcases/fail10.c @@ -0,0 +1,4 @@ +int main() { + int a[2][3]; + a[1][3][3] = 3; +} diff --git a/testcases/fail11.c b/testcases/fail11.c new file mode 100644 index 0000000..4aa213a --- /dev/null +++ b/testcases/fail11.c @@ -0,0 +1,4 @@ +int main() { + int a[2][3]; + a[1] = 3; +} diff --git a/testcases/fail8.c b/testcases/fail8.c new file mode 100644 index 0000000..21efd5f --- /dev/null +++ b/testcases/fail8.c @@ -0,0 +1,5 @@ +struct { + int f(); +}; +int main() { +} diff --git a/testcases/localfunc.c b/testcases/localfunc.c new file mode 100644 index 0000000..8012c6f --- /dev/null +++ b/testcases/localfunc.c @@ -0,0 +1,4 @@ +int f(int a); +int main() { + int f(int a, int b); +} -- cgit v1.2.3