aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2009-03-09 23:32:36 +0000
committerChristopher Li <sparse@chrisli.org>2009-07-18 05:30:09 +0000
commit47567023ae85e9c8428585da298e6d6613a86ab1 (patch)
tree6922e78595ef0c3636b83fc7930aa808ae61eeb3
parentFix declaration_specifiers() handling of typedef name shadowed by NS_SYMBOL (diff)
downloadsparse-47567023ae85e9c8428585da298e6d6613a86ab1.tar.gz
sparse-47567023ae85e9c8428585da298e6d6613a86ab1.tar.bz2
sparse-47567023ae85e9c8428585da298e6d6613a86ab1.zip
Fix __label__ handling
a) __label__ in gcc is not a type, it's a statement. Accepted in the beginning of compound-statement, has form __label__ ident-list; b) instead of crapping into NS_SYMBOL namespace (and consequent shadowing issues), reassign the namespace to NS_LABEL after we'd bound it. We'll get block scope and label namespace, i.e. what we get in gcc. c) MOD_LABEL can be dropped now. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Christopher Li <sparse@chrisli.org>
-rw-r--r--gdbhelpers3
-rw-r--r--ident-list.h1
-rw-r--r--parse.c55
-rw-r--r--symbol.h1
-rw-r--r--validation/label-scope.c12
5 files changed, 40 insertions, 32 deletions
diff --git a/gdbhelpers b/gdbhelpers
index 7223ffd..e28417a 100644
--- a/gdbhelpers
+++ b/gdbhelpers
@@ -146,9 +146,6 @@ define gdb_show_ctype
if ($arg0->modifiers & MOD_TOPLEVEL)
printf "MOD_TOPLEVEL "
end
- if ($arg0->modifiers & MOD_LABEL)
- printf "MOD_LABEL "
- end
if ($arg0->modifiers & MOD_ASSIGNED)
printf "MOD_ASSIGNED "
end
diff --git a/ident-list.h b/ident-list.h
index e22084e..29ddeca 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -31,6 +31,7 @@ IDENT(alignof); IDENT_RESERVED(__alignof); IDENT_RESERVED(__alignof__);
IDENT_RESERVED(__sizeof_ptr__);
IDENT_RESERVED(__builtin_types_compatible_p);
IDENT_RESERVED(__builtin_offsetof);
+IDENT_RESERVED(__label__);
/* Attribute names */
IDENT(packed); IDENT(__packed__);
diff --git a/parse.c b/parse.c
index 8e18d54..04558a5 100644
--- a/parse.c
+++ b/parse.c
@@ -372,8 +372,6 @@ static struct init_keyword {
{ "_Bool", NS_TYPEDEF, .type = &bool_ctype, .op = &spec_op },
/* Predeclared types */
- { "__label__", NS_TYPEDEF, MOD_LABEL,
- .type =&label_ctype, .op = &spec_op },
{ "__builtin_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op },
/* Extended types */
@@ -594,28 +592,6 @@ static struct symbol * alloc_indirect_symbol(struct position pos, struct ctype *
return sym;
}
-static struct symbol *lookup_or_create_symbol(enum namespace ns, enum type type, struct token *token)
-{
- struct symbol *sym = lookup_symbol(token->ident, ns);
- if (!sym) {
- sym = alloc_symbol(token->pos, type);
- bind_symbol(sym, token->ident, ns);
- if (type == SYM_LABEL)
- fn_local_symbol(sym);
- }
- return sym;
-}
-
-static struct symbol * local_label(struct token *token)
-{
- struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL);
-
- if (sym && sym->ctype.modifiers & MOD_LABEL)
- return sym;
-
- return NULL;
-}
-
/*
* NOTE! NS_LABEL is not just a different namespace,
* it also ends up using function scope instead of the
@@ -623,10 +599,13 @@ static struct symbol * local_label(struct token *token)
*/
struct symbol *label_symbol(struct token *token)
{
- struct symbol *sym = local_label(token);
- if (sym)
- return sym;
- return lookup_or_create_symbol(NS_LABEL, SYM_LABEL, token);
+ struct symbol *sym = lookup_symbol(token->ident, NS_LABEL);
+ if (!sym) {
+ sym = alloc_symbol(token->pos, SYM_LABEL);
+ bind_symbol(sym, token->ident, NS_LABEL);
+ fn_local_symbol(sym);
+ }
+ return sym;
}
static struct token *struct_union_enum_specifier(enum type type,
@@ -2149,9 +2128,29 @@ static struct token *statement(struct token *token, struct statement **tree)
return expression_statement(token, &stmt->expression);
}
+/* gcc extension - __label__ ident-list; in the beginning of compound stmt */
+static struct token *label_statement(struct token *token)
+{
+ while (token_type(token) == TOKEN_IDENT) {
+ struct symbol *sym = alloc_symbol(token->pos, SYM_LABEL);
+ /* it's block-scope, but we want label namespace */
+ bind_symbol(sym, token->ident, NS_SYMBOL);
+ sym->namespace = NS_LABEL;
+ fn_local_symbol(sym);
+ token = token->next;
+ if (!match_op(token, ','))
+ break;
+ token = token->next;
+ }
+ return expect(token, ';', "at end of label declaration");
+}
+
static struct token * statement_list(struct token *token, struct statement_list **list)
{
int seen_statement = 0;
+ while (token_type(token) == TOKEN_IDENT &&
+ token->ident == &__label___ident)
+ token = label_statement(token->next);
for (;;) {
struct statement * stmt;
if (eof_token(token))
diff --git a/symbol.h b/symbol.h
index f9944bf..f58c80a 100644
--- a/symbol.h
+++ b/symbol.h
@@ -207,7 +207,6 @@ struct symbol {
#define MOD_ACCESSED 0x400000
#define MOD_TOPLEVEL 0x800000 // scoping..
-#define MOD_LABEL 0x1000000
#define MOD_ASSIGNED 0x2000000
#define MOD_TYPE 0x4000000
#define MOD_SAFE 0x8000000 // non-null/non-trapping pointer
diff --git a/validation/label-scope.c b/validation/label-scope.c
new file mode 100644
index 0000000..7af3d91
--- /dev/null
+++ b/validation/label-scope.c
@@ -0,0 +1,12 @@
+static int f(int n)
+{
+ __label__ n;
+n: return n;
+}
+static int g(int n)
+{
+n: return n;
+}
+/*
+ * check-name: __label__ scope
+ */