summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c11
-rw-r--r--scope.c1
-rw-r--r--symbol.c18
-rw-r--r--symbol.h1
4 files changed, 27 insertions, 4 deletions
diff --git a/parse.c b/parse.c
index 91569f6..245d92f 100644
--- a/parse.c
+++ b/parse.c
@@ -607,7 +607,7 @@ static void start_iterator(struct statement *stmt)
static void end_iterator(void)
{
- start_symbol_scope();
+ end_symbol_scope();
}
static void start_switch(struct statement *stmt)
@@ -625,7 +625,7 @@ static void start_switch(struct statement *stmt)
static void end_switch(void)
{
- start_symbol_scope();
+ end_symbol_scope();
}
struct token *statement(struct token *token, struct statement **tree)
@@ -944,8 +944,9 @@ static struct token *external_declaration(struct token *token, struct symbol_lis
if (decl->ctype.modifiers & MOD_EXTERN) {
if (!(decl->ctype.modifiers & MOD_INLINE))
warn(decl->pos, "function with external linkage has definition");
- decl->ctype.modifiers &= ~MOD_EXTERN;
}
+ if (!(decl->ctype.modifiers & MOD_STATIC))
+ decl->ctype.modifiers |= MOD_EXTERN;
base_type->stmt = alloc_statement(token->pos, STMT_COMPOUND);
start_function_scope();
symbol_iterate(base_type->arguments, declare_argument, decl);
@@ -953,6 +954,7 @@ static struct token *external_declaration(struct token *token, struct symbol_lis
end_function_scope();
if (!(decl->ctype.modifiers & MOD_INLINE))
add_symbol(list, decl);
+ check_declaration(decl);
return expect(token, '}', "at end of function");
}
if (!(decl->ctype.modifiers & MOD_STATIC))
@@ -969,7 +971,8 @@ static struct token *external_declaration(struct token *token, struct symbol_lis
}
if (!is_typedef && !(decl->ctype.modifiers & (MOD_EXTERN | MOD_INLINE)))
add_symbol(list, decl);
-
+ check_declaration(decl);
+
if (!match_op(token, ','))
break;
diff --git a/scope.c b/scope.c
index de240f0..79db655 100644
--- a/scope.c
+++ b/scope.c
@@ -20,6 +20,7 @@ struct scope *block_scope = &toplevel_scope,
void bind_scope(struct symbol *sym, struct scope *scope)
{
+ sym->scope = scope;
add_symbol(&scope->symbols, sym);
}
diff --git a/symbol.c b/symbol.c
index 670fd97..2c56ad1 100644
--- a/symbol.c
+++ b/symbol.c
@@ -267,6 +267,24 @@ struct symbol *examine_symbol_type(struct symbol * sym)
return sym;
}
+void check_declaration(struct symbol *sym)
+{
+ struct symbol *next = sym;
+
+ while ((next = next->next_id) != NULL) {
+ if (next->namespace != sym->namespace)
+ continue;
+ if (sym->scope == next->scope) {
+ sym->same_symbol = next;
+ return;
+ }
+ if (sym->ctype.modifiers & next->ctype.modifiers & MOD_EXTERN) {
+ sym->same_symbol = next;
+ return;
+ }
+ }
+}
+
void bind_symbol(struct symbol *sym, struct ident *ident, enum namespace ns)
{
struct scope *scope;
diff --git a/symbol.h b/symbol.h
index e7b5fbb..ac8ab10 100644
--- a/symbol.h
+++ b/symbol.h
@@ -191,5 +191,6 @@ extern const char *show_typename(struct symbol *sym);
extern void debug_symbol(struct symbol *);
extern void merge_type(struct symbol *sym, struct symbol *base_type);
+extern void check_declaration(struct symbol *sym);
#endif /* SEMANTIC_H */