aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--const.h2
-rw-r--r--semantics.c510
-rw-r--r--testcases/local_struct.c7
-rw-r--r--testcases/pass.c6
-rw-r--r--testcases/void_decl.c3
-rw-r--r--testcases/void_decl2.c5
6 files changed, 280 insertions, 253 deletions
diff --git a/const.h b/const.h
index 29d1123..88a28a4 100644
--- a/const.h
+++ b/const.h
@@ -30,4 +30,6 @@ enum {
#define MAX_ERROR_BUFF 1024
#define INT_SIZE 4
#define CHAR_SIZE 1
+#define FLAG_FUNC_CHK (1 << 0)
+#define FLAG_FUNC_DEF (1 << 1)
#endif
diff --git a/semantics.c b/semantics.c
index 87d502f..05792cc 100644
--- a/semantics.c
+++ b/semantics.c
@@ -245,40 +245,6 @@ void cscope_exit(CScope_t cs) {
free(top_o);
}
-void ctable_debug_print(CTable_t ct) {
- int i;
- fprintf(stderr, "*** CTable ***\n");
- for (i = 0; i < MAX_TABLE_SIZE; i++)
- if (ct->head[i])
- {
- CTNode *p;
- fprintf(stderr, "[%04d]", i);
- for (p = ct->head[i]; p; p = p->next)
- fprintf(stderr, "->[%s:%d]", ct->pfunc(p->val), p->lvl);
- fprintf(stderr, "\n");
- }
- fprintf(stderr, "*** CTable ***\n");
-}
-
-void cscope_debug_print(CScope_t cs) {
- int lvl = cs->lvl;
- CSNode *p;
- CSElem *tp;
- fprintf(stderr, "\n****** CScope ******\n");
- for (p = cs->top; p; p = p->next)
- {
- fprintf(stderr, "Level %d:\n", lvl--);
- for (tp = p->symlist; tp; tp = tp->next)
- fprintf(stderr, "%s ", csymbol_print(tp->sym));
- fprintf(stderr, "\n\n");
- }
- fprintf(stderr, "IDs:\n");
- ctable_debug_print(cs->ids);
- fprintf(stderr, "Tags:\n");
- ctable_debug_print(cs->tags);
- fprintf(stderr, "****** CScope ******\n\n");
-}
-
CSymbol_t cscope_lookup(CScope_t cs, const char *name, int nspace) {
if (nspace == NS_ID)
return ctable_lookup(cs->ids, name);
@@ -295,30 +261,6 @@ unsigned int bkdr_hash(const char *str) {
return hv;
}
-const char *csymbol_print(void *csym) {
- CSymbol_t p = (CSymbol_t)csym;
- static char buff[MAX_DEBUG_PRINT_BUFF];
- switch (p->kind)
- {
- case CVAR:
- sprintf(buff, "%s@%lx", p->rec.var->name, (size_t)p->rec.var);
- break;
- case CTYPE:
- sprintf(buff, "%s@%lx", p->rec.type->name, (size_t)p->rec.type);
- break;
- case CDEF:
- sprintf(buff, "%s@%lx", p->rec.def->name, (size_t)p->rec.def);
- }
- return buff;
-}
-
-const char *ctable_cvar_print(void *var) {
- static char buff[MAX_DEBUG_PRINT_BUFF];
- sprintf(buff, "%s@%lx", ((CVar_t )var)->name, (size_t)var);
- return buff;
-}
-
-
CVar_t cvar_create(const char *name, CType_t type, CNode *ast) {
CVar_t cv = NEW(CVar);
cv->name = name;
@@ -341,129 +283,6 @@ CType_t ctype_create(const char *name, int type, CNode *ast) {
return ct;
}
-void ctype_print_(CType_t, int lvl);
-void print_tabs(int tnum) { while (tnum--) fprintf(stderr, "\t"); }
-void ctype_pre_(CType_t type, int *lvl) {
- int t= type->type;
- if (t == CARR || t == CFUNC || t == CUNION || t == CSTRUCT)
- {
- fprintf(stderr, "\n");
- *lvl += 2;
- print_tabs(*lvl);
- }
-}
-
-void cvar_print_(CVar_t cv, int lvl) {
- fprintf(stderr, "[var@%lx:%s :: ", (size_t)cv, cv->name);
- ctype_pre_(cv->type, &lvl);
- ctype_print_(cv->type, lvl);
- fprintf(stderr, "]");
-}
-
-void cdef_print_(CDef_t cd, int lvl) {
- fprintf(stderr, "[def@%lx:%s :: ", (size_t)cd, cd->name);
- ctype_pre_(cd->type, &lvl);
- ctype_print_(cd->type, lvl);
- fprintf(stderr, "]");
-}
-
-void ctype_print_(CType_t ct, int lvl) {
- switch (ct->type)
- {
- case CINT:
- fprintf(stderr, "[int]"); break;
- case CCHAR:
- fprintf(stderr, "[char]"); break;
- case CVOID:
- fprintf(stderr, "[void]"); break;
- case CSTRUCT:
- case CUNION:
- {
- CTable_t f = ct->rec.fields;
- int i;
- CTNode *fn;
- lvl++;
- fprintf(stderr, "[%s@%lx:{name:%s}",
- ct->type == CSTRUCT ? "struct" : "union",
- (size_t)ct,
- ct->name);
-
- fprintf(stderr, "{fields:");
- if (f)
- {
- fprintf(stderr, "\n");
- int first = 1;
- for (i = 0; i < MAX_TABLE_SIZE; i++)
- for (fn = f->head[i]; fn; fn = fn->next)
- {
- fprintf(stderr, "%s", first ? (first = 0, "") : ",\n");
- print_tabs(lvl);
- cvar_print_((CVar_t)fn->val, lvl);
- }
- }
- fprintf(stderr, "}]");
- }
- break;
- case CARR:
- {
- CType_t type = ct->rec.arr.elem;
- fprintf(stderr, "[arr:{len:%d}]->", ct->rec.arr.len);
- ctype_pre_(type, &lvl);
- ctype_print_(type, lvl);
- }
- break;
- case CPTR:
- {
- CType_t type = ct->rec.ref;
- fprintf(stderr, "[ptr]->");
- ctype_pre_(type, &lvl);
- ctype_print_(type, lvl);
- }
- break;
- case CFUNC:
- {
- CType_t type = ct->rec.func.ret;
- CVar_t p;
- lvl++;
- fprintf(stderr, "[func:{name:%s}\n", ct->name);
- print_tabs(lvl);
- fprintf(stderr, "{params:");
- if (ct->rec.func.params)
- {
- fprintf(stderr, "\n");
- for (p = ct->rec.func.params; p; p = p->next)
- {
- print_tabs(lvl + 1);
- cvar_print_(p, lvl + 1);
- if (p->next) fprintf(stderr, ",\n");
- }
- }
- /* print_tabs(lvl); */
- fprintf(stderr, "}\n");
- print_tabs(lvl);
- fprintf(stderr, "{local:");
- if (ct->rec.func.local)
- {
- fprintf(stderr, "\n");
- for (p = ct->rec.func.local; p; p = p->next)
- {
- print_tabs(lvl + 1);
- cvar_print_(p, lvl + 1);
- if (p->next) fprintf(stderr, ",\n");
- }
- }
- fprintf(stderr, "}]->");
- ctype_pre_(type, &lvl);
- ctype_print_(type, lvl);
- }
- break;
- }
-}
-
-void ctype_print(CType_t ct) { ctype_print_(ct, 0); }
-void cvar_print(CVar_t cv) { cvar_print_(cv, 0); }
-void cdef_print(CDef_t cd) { cdef_print_(cd, 0); }
-
static CType_t struct_type_merge(CType_t new, CScope_t scope) {
/* Note: we shall try to lookup first instead of pushing !! */
CSymbol_t lu = cscope_lookup(scope, new->name, NS_TAG);
@@ -667,11 +486,11 @@ CVar_t semantics_params(CNode *p, CScope_t scope) {
}
ExpType semantics_exp(CNode *, CScope_t);
-CVar_t semantics_declr(CNode *p, CType_t type_spec, CScope_t scope, int func_chk) {
+CVar_t semantics_declr(CNode *p, CType_t type_spec, CScope_t scope, int flag) {
CVar_t type;
if (p->type == ID)
{
- if (!func_chk) CHECK_CVOID(p->rec.strval, p);
+ if (!(flag & FLAG_FUNC_CHK)) CHECK_CVOID(p->rec.strval, p);
return cvar_create(p->rec.strval, type_spec, p);
}
if (p->type == NOP) /* type name */
@@ -681,14 +500,19 @@ CVar_t semantics_declr(CNode *p, CType_t type_spec, CScope_t scope, int func_chk
case DECLR_FUNC:
{
CType_t func = ctype_create("", CFUNC, p); /* function declr */
- cscope_enter(scope);
- func->rec.func.params = semantics_params(p->chd->next, scope);
- cscope_exit(scope);
+ if (flag & FLAG_FUNC_DEF) /* function def */
+ func->rec.func.params = semantics_params(p->chd->next, scope);
+ else /* function declaration */
+ {
+ cscope_enter(scope);
+ func->rec.func.params = semantics_params(p->chd->next, scope);
+ cscope_exit(scope);
+ }
/* incomplete type */
func->rec.func.local = NULL;
func->rec.func.ret = type_spec; /* might be an incomplete type */
func->rec.func.body = NULL; /* not a definition */
- type = semantics_declr(p->chd, func, scope, 1);
+ type = semantics_declr(p->chd, func, scope, flag | FLAG_FUNC_CHK);
if (type_spec->type == CARR)
ERROR((p, "'%s' declared as function returning an array", type->name));
if (type_spec->type == CFUNC)
@@ -1567,20 +1391,21 @@ CVar_t semantics_comp(CNode *p, CScope_t scope) {
CType_t semantics_func(CNode *p, CScope_t scope) {
CHECK_TYPE(p, FUNC_DEF);
- CVar_t head = semantics_declr(p->chd->next,
+ CVar_t head;
+ CType_t func, efunc, rt;
+ cscope_enter(scope); /* enter function local scope */
+ head = semantics_declr(p->chd->next,
semantics_type_spec(p->chd, scope),
- scope, 0);
- CType_t func = head->type, efunc;
- CType_t rt = func->rec.func.ret;
-
+ scope, FLAG_FUNC_DEF);
+ func = head->type;
+ rt = func->rec.func.ret;
if (rt->type != CVOID && !type_is_complete(rt))
ERROR((func->rec.func.ret->ast, "return type is an incomplete type"));
- scope->func = func;
func->rec.func.body = p->chd->next->next;
func->name = head->name;
+ scope->func = func;
free(head);
- cscope_enter(scope); /* enter function local scope */
{ /* Note: here is a dirty hack to forcibly push function definition to
the global scope, while all the types specified in parameters retain in local scope.
The key point is to make sure semantics_params does not push any var */
@@ -1630,6 +1455,244 @@ CType_t make_builtin_func(const char *name, CType_t rt) {
return func;
}
+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_stack = NULL;
+}
+
+int is_identifier(const char *name) {
+ CSymbol_t lu;
+ 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_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);
+}
+
+CDef_t cdef_create(const char *name, CType_t type, CNode *ast) {
+ CDef_t cd = NEW(CDef);
+ cd->name = name;
+ cd->type = type;
+ cd->ast = ast;
+ return cd;
+}
+
+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); }
+
+void ctable_debug_print(CTable_t ct) {
+ int i;
+ fprintf(stderr, "*** CTable ***\n");
+ for (i = 0; i < MAX_TABLE_SIZE; i++)
+ if (ct->head[i])
+ {
+ CTNode *p;
+ fprintf(stderr, "[%04d]", i);
+ for (p = ct->head[i]; p; p = p->next)
+ fprintf(stderr, "->[%s:%d]", ct->pfunc(p->val), p->lvl);
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "*** CTable ***\n");
+}
+
+void cscope_debug_print(CScope_t cs) {
+ int lvl = cs->lvl;
+ CSNode *p;
+ CSElem *tp;
+ fprintf(stderr, "\n****** CScope ******\n");
+ for (p = cs->top; p; p = p->next)
+ {
+ fprintf(stderr, "Level %d:\n", lvl--);
+ for (tp = p->symlist; tp; tp = tp->next)
+ fprintf(stderr, "%s ", csymbol_print(tp->sym));
+ fprintf(stderr, "\n\n");
+ }
+ fprintf(stderr, "IDs:\n");
+ ctable_debug_print(cs->ids);
+ fprintf(stderr, "Tags:\n");
+ ctable_debug_print(cs->tags);
+ fprintf(stderr, "****** CScope ******\n\n");
+}
+
+const char *ctable_cvar_print(void *var) {
+ static char buff[MAX_DEBUG_PRINT_BUFF];
+ sprintf(buff, "%s@%lx", ((CVar_t )var)->name, (size_t)var);
+ return buff;
+}
+
+const char *csymbol_print(void *csym) {
+ CSymbol_t p = (CSymbol_t)csym;
+ static char buff[MAX_DEBUG_PRINT_BUFF];
+ switch (p->kind)
+ {
+ case CVAR:
+ sprintf(buff, "%s@%lx", p->rec.var->name, (size_t)p->rec.var);
+ break;
+ case CTYPE:
+ sprintf(buff, "%s@%lx", p->rec.type->name, (size_t)p->rec.type);
+ break;
+ case CDEF:
+ sprintf(buff, "%s@%lx", p->rec.def->name, (size_t)p->rec.def);
+ }
+ return buff;
+}
+
+void ctype_print_(CType_t, int lvl);
+void print_tabs(int tnum) { while (tnum--) fprintf(stderr, " "); }
+void ctype_pre_(CType_t type, int lvl) {
+ int t= type->type;
+ if (t == CARR || t == CFUNC || t == CUNION || t == CSTRUCT)
+ {
+ fprintf(stderr, "\n");
+ print_tabs(lvl);
+ }
+}
+
+void cvar_print_(CVar_t cv, int lvl) {
+ fprintf(stderr, "[var@%lx:%s :: ", (size_t)cv, cv->name);
+ ctype_pre_(cv->type, ++lvl);
+ ctype_print_(cv->type, lvl);
+ fprintf(stderr, "]");
+}
+
+void cdef_print_(CDef_t cd, int lvl) {
+ fprintf(stderr, "[def@%lx:%s :: ", (size_t)cd, cd->name);
+ ctype_pre_(cd->type, ++lvl);
+ ctype_print_(cd->type, lvl);
+ fprintf(stderr, "]");
+}
+
+void ctype_print_(CType_t ct, int lvl) {
+ switch (ct->type)
+ {
+ case CINT:
+ fprintf(stderr, "[int]"); break;
+ case CCHAR:
+ fprintf(stderr, "[char]"); break;
+ case CVOID:
+ fprintf(stderr, "[void]"); break;
+ case CSTRUCT:
+ case CUNION:
+ {
+ CTable_t f = ct->rec.fields;
+ int i;
+ CTNode *fn;
+ lvl++;
+ fprintf(stderr, "[%s@%lx:{name:%s}",
+ ct->type == CSTRUCT ? "struct" : "union",
+ (size_t)ct,
+ ct->name);
+
+ fprintf(stderr, "{fields:");
+ if (f)
+ {
+ fprintf(stderr, "\n");
+ int first = 1;
+ for (i = 0; i < MAX_TABLE_SIZE; i++)
+ for (fn = f->head[i]; fn; fn = fn->next)
+ {
+ fprintf(stderr, "%s", first ? (first = 0, "") : ",\n");
+ print_tabs(lvl);
+ cvar_print_((CVar_t)fn->val, lvl);
+ }
+ }
+ fprintf(stderr, "}]");
+ }
+ break;
+ case CARR:
+ {
+ CType_t type = ct->rec.arr.elem;
+ fprintf(stderr, "[arr:{len:%d}]->", ct->rec.arr.len);
+ ctype_pre_(type, ++lvl);
+ ctype_print_(type, lvl);
+ }
+ break;
+ case CPTR:
+ {
+ CType_t type = ct->rec.ref;
+ fprintf(stderr, "[ptr]->");
+ ctype_pre_(type, ++lvl);
+ ctype_print_(type, lvl);
+ }
+ break;
+ case CFUNC:
+ {
+ CType_t type = ct->rec.func.ret;
+ CVar_t p;
+ lvl++;
+ fprintf(stderr, "[func:{name:%s}\n", ct->name);
+ print_tabs(lvl);
+ fprintf(stderr, "{params:");
+ if (ct->rec.func.params)
+ {
+ fprintf(stderr, "\n");
+ for (p = ct->rec.func.params; p; p = p->next)
+ {
+ print_tabs(lvl + 1);
+ cvar_print_(p, lvl + 1);
+ if (p->next) fprintf(stderr, ",\n");
+ }
+ }
+ /* print_tabs(lvl); */
+ fprintf(stderr, "}\n");
+ print_tabs(lvl);
+ fprintf(stderr, "{local:");
+ if (ct->rec.func.local)
+ {
+ fprintf(stderr, "\n");
+ for (p = ct->rec.func.local; p; p = p->next)
+ {
+ print_tabs(lvl + 1);
+ cvar_print_(p, lvl + 1);
+ if (p->next) fprintf(stderr, ",\n");
+ }
+ }
+ fprintf(stderr, "}]->");
+ ctype_pre_(type, lvl);
+ ctype_print_(type, lvl);
+ }
+ break;
+ }
+}
+
+void ctype_print(CType_t ct) { ctype_print_(ct, 0); }
+void cvar_print(CVar_t cv) { cvar_print_(cv, 0); }
+void cdef_print(CDef_t cd) { cdef_print_(cd, 0); }
+
void semantics_check(CNode *p) {
CScope_t scope = cscope_create();
basic_type_int = ctype_create("int", CINT, NULL);
@@ -1692,62 +1755,3 @@ void semantics_check(CNode *p) {
}
cnode_debug_print(ast_root, 1);
}
-
-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_stack = NULL;
-}
-
-int is_identifier(const char *name) {
- CSymbol_t lu;
- 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_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);
-}
-
-CDef_t cdef_create(const char *name, CType_t type, CNode *ast) {
- CDef_t cd = NEW(CDef);
- cd->name = name;
- cd->type = type;
- cd->ast = ast;
- return cd;
-}
-
-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/testcases/local_struct.c b/testcases/local_struct.c
new file mode 100644
index 0000000..28cb223
--- /dev/null
+++ b/testcases/local_struct.c
@@ -0,0 +1,7 @@
+struct A {int x; int y; } b;
+int f(struct A {int a;} p) {
+ struct A a;
+ a.x;
+}
+int main() {
+}
diff --git a/testcases/pass.c b/testcases/pass.c
index 9711611..5d5b3dc 100644
--- a/testcases/pass.c
+++ b/testcases/pass.c
@@ -134,6 +134,12 @@ int typedef_struct() {
a.x = 1;
}
+struct AA {int x; int y; };
+int aa(struct AA {int a;} p) {
+ struct AA a;
+ a.a;
+}
+
int main() {
n.x = 1;
n.y = 2;
diff --git a/testcases/void_decl.c b/testcases/void_decl.c
new file mode 100644
index 0000000..8a68b18
--- /dev/null
+++ b/testcases/void_decl.c
@@ -0,0 +1,3 @@
+void a;
+int main() {
+}
diff --git a/testcases/void_decl2.c b/testcases/void_decl2.c
new file mode 100644
index 0000000..30c7af6
--- /dev/null
+++ b/testcases/void_decl2.c
@@ -0,0 +1,5 @@
+struct {
+ void a;
+};
+int main() {
+}