aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2014-04-13 12:31:28 +0800
committerTeddy <ted.sybil@gmail.com>2014-04-13 12:31:28 +0800
commite8cbc056b7472c2c5438bdbd6571a40d5e1bcfcd (patch)
treeb6128928ede277091f0669ebcada90e7c86cbb40
parent47ce7f1266ce1a68551c839fdcfb99c45cdc186e (diff)
fixed bugs in typedef
-rw-r--r--cibic.y56
-rw-r--r--semantics.c51
-rw-r--r--semantics.h16
-rw-r--r--testcases/pass.c1
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 <stdio.h>
#include <stdlib.h>
#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);