From e8cbc056b7472c2c5438bdbd6571a40d5e1bcfcd Mon Sep 17 00:00:00 2001 From: Teddy Date: Sun, 13 Apr 2014 12:31:28 +0800 Subject: fixed bugs in typedef --- cibic.y | 56 +++++++++++++++++++++++++++++--------------------------- semantics.c | 51 ++++++++++++++++++++++++++++++++------------------- semantics.h | 16 +++++++++++----- testcases/pass.c | 1 + 4 files changed, 73 insertions(+), 51 deletions(-) diff --git a/cibic.y b/cibic.y index 6e25724..1a644a4 100644 --- a/cibic.y +++ b/cibic.y @@ -2,6 +2,7 @@ #include #include #include "ast.h" +#include "semantics.h" %} %union { int intval; @@ -32,29 +33,28 @@ prog_list | prog_list function_definition { $$ = cnode_list_append($1, $2); } declaration - : KW_TYPEDEF type_specifier { enter_typedef(); } declarators ';' { + : KW_TYPEDEF type_specifier { def_exit(); def_enter(IN_TYPEDEF); } declarators ';' { $$ = cnode_add_loc(cnode_create_typedef( $2, cnode_add_loc(cnode_list_wrap(DECLRS, $4), @4)), @$); - clear_state(); + def_exit(); } | type_specifier ';' { $$ = cnode_add_loc(cnode_create_decl( $1, cnode_list_wrap(INIT_DECLRS, cnode_create_nop())), @$); - clear_state(); + def_exit(); } | type_specifier init_declarators ';' { $$ = cnode_add_loc(cnode_create_decl( $1, cnode_add_loc(cnode_list_wrap(INIT_DECLRS, $2), @2)), @$); - clear_state(); + def_exit(); } function_definition - : type_specifier declarator compound_statement { - $$ = cnode_add_loc(cnode_create_func($1, $2, $3), @$); - clear_state(); + : type_specifier declarator { def_exit(); } compound_statement { + $$ = cnode_add_loc(cnode_create_func($1, $2, $4), @$); } parameters @@ -84,22 +84,23 @@ array_initializer $$ = cnode_list_append(cnode_add_loc($1, @1), $3); } type_specifier - : KW_VOID { $$ = cnode_add_loc(cnode_create_type_spec(KW_VOID, 0), @$); force_id(); } - | KW_CHAR { $$ = cnode_add_loc(cnode_create_type_spec(KW_CHAR, 0), @$); force_id(); } - | KW_INT { $$ = cnode_add_loc(cnode_create_type_spec(KW_INT, 0), @$); force_id(); } - | struct_or_union identifier '{' struct_fields '}' { - $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_add_loc(cnode_list_wrap(FIELDS, $4), @4)), @$); - force_id(); + : KW_VOID { $$ = cnode_add_loc(cnode_create_type_spec(KW_VOID, 0), @$); def_enter(FORCE_ID); } + | KW_CHAR { $$ = cnode_add_loc(cnode_create_type_spec(KW_CHAR, 0), @$); def_enter(FORCE_ID); } + | KW_INT { $$ = cnode_add_loc(cnode_create_type_spec(KW_INT, 0), @$); def_enter(FORCE_ID); } + | struct_or_union identifier {def_exit(); }'{' struct_fields '}' { + $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_add_loc(cnode_list_wrap(FIELDS, $5), @5)), @$); + def_enter(FORCE_ID); } - | struct_or_union '{' struct_fields '}' { - $$ = cnode_add_loc(cnode_create_type_spec($1, 2, cnode_create_nop(), cnode_add_loc(cnode_list_wrap(FIELDS, $3), @3)), @$); - force_id(); + | struct_or_union {def_exit(); }'{' struct_fields '}' { + $$ = cnode_add_loc(cnode_create_type_spec($1, 2, cnode_create_nop(), cnode_add_loc(cnode_list_wrap(FIELDS, $4), @4)), @$); + def_enter(FORCE_ID); } | struct_or_union identifier { $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_create_nop()), @$); - force_id(); + def_exit(); + def_enter(FORCE_ID); } - | user_type { $$ = cnode_add_loc(cnode_create_type_spec(USER_TYPE, 1, $1), @$); force_id(); } + | user_type { $$ = cnode_add_loc(cnode_create_type_spec(USER_TYPE, 1, $1), @$); def_enter(FORCE_ID); } user_type : USER_TYPE { $$ = cnode_add_loc(cnode_create_identifier($1), @$); } @@ -113,26 +114,27 @@ struct_field cnode_create_struct_field( $1, cnode_add_loc(cnode_list_wrap(DECLRS, $2), @2)), @$); - clear_state(); + def_exit(); } struct_or_union - : KW_STRUCT { $$ = KW_STRUCT; force_id(); } - | KW_UNION { $$ = KW_UNION; force_id(); } + : KW_STRUCT { $$ = KW_STRUCT; def_enter(FORCE_ID); } + | KW_UNION { $$ = KW_UNION; def_enter(FORCE_ID); } plain_declaration : type_specifier declarator { $$ = cnode_add_loc(cnode_create_plain_decl($1, $2), @$); - clear_state(); + def_exit(); } direct_declarator : identifier { push($1->rec.strval); } | '(' declarator ')' { $$ = $2; } - | direct_declarator '(' parameters ')' { + | direct_declarator { def_enter(NONE); } '(' parameters ')' { $$ = cnode_add_loc(cnode_create_declr( DECLR_FUNC, 2, $1, - cnode_add_loc(cnode_list_wrap(PARAMS, $3), @3)), @$); + cnode_add_loc(cnode_list_wrap(PARAMS, $4), @4)), @$); + def_exit(); } | direct_declarator '[' constant_expression ']' { $$ = cnode_add_loc(cnode_create_declr(DECLR_ARR, 2, $1, $3), @$); @@ -155,11 +157,11 @@ expression_statement | expression ';' { $$ = cnode_add_loc(cnode_create_stmt(STMT_EXP, 1, $1), @$); } compound_statement - : { clear_state(); enter_block(); } '{' comp_decls comp_stmts '}' { + : { block_enter(); } '{' comp_decls comp_stmts '}' { $$ = cnode_add_loc( cnode_create_stmt(STMT_COMP, 2, cnode_add_loc(cnode_list_wrap(COMP_DECLS, $3), @3), cnode_add_loc(cnode_list_wrap(COMP_STMTS, $4), @4)), @$); - exit_block(); + block_exit(); } comp_decls @@ -314,7 +316,7 @@ cast_expression type_name : type_specifier abstract_declarator_opt { $$ = cnode_add_loc(cnode_create_declr(0, 2, $1, $2), @$); - clear_state(); + def_exit(); } abstract_declarator_opt diff --git a/semantics.c b/semantics.c index da2a42b..9013aac 100644 --- a/semantics.c +++ b/semantics.c @@ -1640,33 +1640,36 @@ void semantics_check(CNode *p) { cnode_debug_print(ast_root, 1); } -static CScope_t typedef_scope; -static enum { - NONE, - FORCE_ID, - IN_TYPEDEF -} typedef_state; +typedef struct DNode DNode; +CScope_t typedef_scope; +struct DNode{ + enum DefState kind; + DNode *next; +} *typedef_stack; void cibic_init() { typedef_scope = cscope_create(); - typedef_state = NONE; + typedef_stack = NULL; } int is_identifier(const char *name) { CSymbol_t lu; - /* struct tag */ - /* the parser is reading declarators */ - if (typedef_state == FORCE_ID) return 1; - /* the parser is reading typedef */ - if (typedef_state == IN_TYPEDEF) return 1; - /* no info about name, assume it to be an id by default */ + if (typedef_stack) + { + /* struct tag */ + /* the parser is reading declarators */ + if (typedef_stack->kind == FORCE_ID) return 1; + /* the parser is reading typedef */ + if (typedef_stack->kind == IN_TYPEDEF) return 1; + /* no info about name, assume it to be an id by default */ + } lu = cscope_lookup(typedef_scope, name, NS_ID); if (!lu) return 1; return lu->kind == CVAR; } void push(const char *name) { - if (typedef_state == IN_TYPEDEF) + if (typedef_stack && typedef_stack->kind == IN_TYPEDEF) cscope_push_type(typedef_scope, ctype_create(name, 0, NULL), NS_ID); else cscope_push_var(typedef_scope, cvar_create(name, NULL, NULL), NS_ID); @@ -1680,8 +1683,18 @@ CDef_t cdef_create(const char *name, CType_t type, CNode *ast) { return cd; } -void enter_block() { cscope_enter(typedef_scope); } -void exit_block() { cscope_exit(typedef_scope); } -void force_id() { typedef_state = FORCE_ID; } -void enter_typedef() { typedef_state = IN_TYPEDEF; } -void clear_state() { typedef_state = NONE; } +void def_enter(enum DefState kind) { + DNode *ntop = NEW(DNode); + ntop->kind = kind; + ntop->next = typedef_stack; + typedef_stack = ntop; +} + +void def_exit() { + DNode *ntop = typedef_stack->next; + free(typedef_stack); + typedef_stack = ntop; +} + +void block_enter() { cscope_enter(typedef_scope); } +void block_exit() { cscope_exit(typedef_scope); } diff --git a/semantics.h b/semantics.h index b836ed2..87cd345 100644 --- a/semantics.h +++ b/semantics.h @@ -155,12 +155,18 @@ unsigned int bkdr_hash(const char *str); const char *ctable_cvar_print(void *var); void semantics_check(CNode *ast); + +enum DefState{ + FORCE_ID, + IN_TYPEDEF, + NONE +}; + int is_identifier(const char *name); void push(const char *name); void cibic_init(void); -void enter_block(void); -void exit_block(void); -void force_id(void); -void enter_typedef(void); -void clear_state(void); +void block_enter(void); +void block_exit(void); +void def_enter(enum DefState kind); +void def_exit(void); #endif diff --git a/testcases/pass.c b/testcases/pass.c index 1727c56..9711611 100644 --- a/testcases/pass.c +++ b/testcases/pass.c @@ -87,6 +87,7 @@ int fc(int fc()) { } int incomp(struct I a); +struct I { int i, j; }; void (*bsd_signal(int sig, void (*func)(int a)))(int b); -- cgit v1.2.3