From 62ac0453c49de5e4a7ac5673bd772c6484d6acf7 Mon Sep 17 00:00:00 2001 From: Teddy Date: Sat, 12 Apr 2014 23:02:31 +0800 Subject: fixed bugs in typedef (with struct/union) --- README.rst | 1 + TODO.rst | 6 +++--- cibic.y | 6 ++++-- semantics.c | 8 ++++++-- testcases/pass.c | 9 +++++++++ 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 91d88d4..b5678f7 100644 --- a/README.rst +++ b/README.rst @@ -11,6 +11,7 @@ Features --------- - Complex declaration support (``int (*a)[10]``, ``int (*f)()``, ``int (*g(int ***e[10]))()``, etc.) - Complex cast support (``(int (*)())addr``, ``(int (*)[10])addr``, etc.) +- `typedef` support (together with complex decl) - Forward declaration - Sophisticated error reporting - User-friendly AST printing diff --git a/TODO.rst b/TODO.rst index 3898fd0..5081b17 100644 --- a/TODO.rst +++ b/TODO.rst @@ -17,10 +17,10 @@ TODO - 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) - - vague var table management + - vague var table management (done) - Not Implemented: - 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) + - initializer checking (done) + - typedef support (via adding mid-rule actions to bision to inform flex) (done) diff --git a/cibic.y b/cibic.y index c3d65ac..66337c9 100644 --- a/cibic.y +++ b/cibic.y @@ -42,6 +42,7 @@ declaration $$ = cnode_add_loc(cnode_create_decl( $1, cnode_list_wrap(INIT_DECLRS, cnode_create_nop())), @$); + exit_declr(); } | type_specifier init_declarators ';' { $$ = cnode_add_loc(cnode_create_decl( @@ -53,6 +54,7 @@ declaration function_definition : type_specifier declarator compound_statement { $$ = cnode_add_loc(cnode_create_func($1, $2, $3), @$); + exit_declr(); } parameters @@ -115,8 +117,8 @@ struct_field } struct_or_union - : KW_STRUCT { $$ = KW_STRUCT; } - | KW_UNION { $$ = KW_UNION; } + : KW_STRUCT { $$ = KW_STRUCT; enter_struct(); } + | KW_UNION { $$ = KW_UNION; enter_struct(); } plain_declaration : type_specifier declarator { diff --git a/semantics.c b/semantics.c index 45571a0..d507e6a 100644 --- a/semantics.c +++ b/semantics.c @@ -773,7 +773,7 @@ void semantics_typedef(CNode *p, CType_t type, CScope_t scope) { if (lu->kind != CDEF) ERROR((def->ast, "'%s' redeclared as different kind of symbol", def->name)); /* FIXME: `typedef int a()` is different from typedef `int a(int)` */ - if (!is_same_type(lu->rec.type, def->type)) + if (!is_same_type(lu->rec.def->type, def->type)) ERROR((def->ast, "conflicting types of '%s'", def->name)); } } @@ -1644,7 +1644,8 @@ static CScope_t typedef_scope; static enum { NONE, TYPEDEF_DECLR, - OTHER_DECLR + OTHER_DECLR, + STRUCT_TAG } typedef_state; void cibic_init() { @@ -1654,6 +1655,8 @@ void cibic_init() { int is_identifier(const char *name) { CSymbol_t lu; + /* struct tag */ + if (typedef_state == STRUCT_TAG) return 1; /* the parser is reading declarators */ if (typedef_state == OTHER_DECLR) return 1; /* the parser is reading typedef */ @@ -1683,4 +1686,5 @@ void enter_block() { cscope_enter(typedef_scope); } void exit_block() { cscope_exit(typedef_scope); } void enter_typedef() { typedef_state = TYPEDEF_DECLR; } void enter_declr() { typedef_state = OTHER_DECLR; } +void enter_struct() { typedef_state = STRUCT_TAG; } void exit_declr() { typedef_state = NONE; } diff --git a/testcases/pass.c b/testcases/pass.c index e567680..1727c56 100644 --- a/testcases/pass.c +++ b/testcases/pass.c @@ -124,6 +124,15 @@ int typedef2() { } } +typedef struct TA { + int x; +} TA; +typedef struct TA TA; +int typedef_struct() { + TA a; + a.x = 1; +} + int main() { n.x = 1; n.y = 2; -- cgit v1.2.3