aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2014-04-12 23:02:31 +0800
committerTeddy <ted.sybil@gmail.com>2014-04-12 23:02:31 +0800
commit62ac0453c49de5e4a7ac5673bd772c6484d6acf7 (patch)
tree04d3f7454afe89cba087b95bffe72bc245934bad
parentbbce3104de593c90b10778a379728f982bc3fdcb (diff)
fixed bugs in typedef (with struct/union)
-rw-r--r--README.rst1
-rw-r--r--TODO.rst6
-rw-r--r--cibic.y6
-rw-r--r--semantics.c8
-rw-r--r--testcases/pass.c9
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;