aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@home.transmeta.com>2003-03-23 18:52:55 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 20:59:38 -0700
commit724d653f51eac7c6428cc0b8e1dc85d9c6f2cfb2 (patch)
treea1d9d204a131ecf5184450c9bd70780e7395c0b2
parent3b5ffd7a07433f1439d633bfb7ef3a3b2888da42 (diff)
downloadsparse-dev-724d653f51eac7c6428cc0b8e1dc85d9c6f2cfb2.tar.gz
Parse type qualifiers properly instead of re-using the declaration
specifiers parsing (which is a proper superset of the much more limited parsing that we wanted at this point). Parse void and ellipsis arguments in function argument lists. Parse named structure member initializers.
-rw-r--r--parse.c71
-rw-r--r--symbol.h1
-rw-r--r--test-lexing.c1
-rw-r--r--test-parsing.c1
4 files changed, 60 insertions, 14 deletions
diff --git a/parse.c b/parse.c
index c07a5604..9253a6fe 100644
--- a/parse.c
+++ b/parse.c
@@ -176,6 +176,30 @@ struct token *attribute_specifier(struct token *token, struct ctype *ctype)
#define MOD_SPECIALBITS (MOD_STRUCTOF | MOD_UNIONOF | MOD_ENUMOF | MOD_ATTRIBUTE | MOD_TYPEOF)
+static struct token *type_qualifiers(struct token *next, struct ctype *ctype)
+{
+ struct token *token;
+ while ( (token = next) != NULL ) {
+ struct symbol *s, *base_type;
+ unsigned long mod;
+
+ next = token->next;
+ if (token->type != TOKEN_IDENT)
+ break;
+ s = lookup_symbol(token->ident, NS_TYPEDEF);
+ if (!s)
+ break;
+ mod = s->ctype.modifiers;
+ base_type = s->ctype.base_type;
+ if (base_type)
+ break;
+ if (mod & ~(MOD_CONST | MOD_VOLATILE))
+ break;
+ ctype->modifiers |= mod;
+ }
+ return token;
+}
+
static struct token *declaration_specifiers(struct token *next, struct ctype *ctype)
{
struct token *token;
@@ -259,10 +283,6 @@ static struct token *declarator(struct token *token, struct symbol **tree, struc
static struct token *direct_declarator(struct token *token, struct symbol **tree, struct token **p)
{
if (p && token->type == TOKEN_IDENT) {
- if (lookup_symbol(token->ident, NS_TYPEDEF)) {
- warn(token, "unexpected type/qualifier");
- return token;
- }
*p = token;
token = token->next;
}
@@ -325,7 +345,7 @@ static struct token *pointer(struct token *token, struct ctype *ctype)
struct symbol *base_type;
force_default_type(ctype);
- modifiers = ctype->modifiers & ~MOD_TYPEDEF;
+ modifiers = ctype->modifiers & ~(MOD_TYPEDEF | MOD_ATTRIBUTE);
base_type = ctype->base_type;
while (match_op(token,'*')) {
@@ -337,7 +357,7 @@ static struct token *pointer(struct token *token, struct ctype *ctype)
modifiers &= MOD_STORAGE;
ctype->base_type = base_type;
- token = declaration_specifiers(token->next, ctype);
+ token = type_qualifiers(token->next, ctype);
}
ctype->modifiers = modifiers;
return token;
@@ -571,17 +591,16 @@ static struct token *parameter_type_list(struct token *token, struct symbol_list
for (;;) {
struct symbol *sym = alloc_symbol(token, SYM_TYPE);
- token = parameter_declaration(token, &sym);
+ if (match_op(token, SPECIAL_ELLIPSIS)) {
+ sym->type = SYM_ELLIPSIS;
+ token = token->next;
+ } else
+ token = parameter_declaration(token, &sym);
add_symbol(list, sym);
if (!match_op(token, ','))
break;
token = token->next;
- if (match_op(token, SPECIAL_ELLIPSIS)) {
- /* FIXME: mark the function */
- token = token->next;
- break;
- }
}
return token;
}
@@ -610,9 +629,27 @@ static struct token *initializer_list(struct token *token, struct ctype *type)
return token;
}
+struct token *parse_named_initializer(struct token *id, struct token *token)
+{
+ struct expression *expr;
+
+ return assignment_expression(token, &expr);
+}
+
struct token *initializer(struct token *token, struct ctype *type)
{
struct expression *expr;
+ struct token *next, *name = NULL;
+
+ next = token->next;
+ if (match_op(token, '.') && (next->type == TOKEN_IDENT) && match_op(next->next, '=')) {
+ name = next;
+ token = next->next->next;
+ } else if ((token->type == TOKEN_IDENT) && match_op(next, ':')) {
+ name = token;
+ token = next->next;
+ }
+
if (match_op(token, '{')) {
token = initializer_list(token->next, type);
return expect(token, '}', "at end of initializer");
@@ -622,8 +659,14 @@ struct token *initializer(struct token *token, struct ctype *type)
static void declare_argument(struct symbol *sym, void *data, int flags)
{
+ struct symbol *decl = data;
+
+ if (sym->type == SYM_ELLIPSIS)
+ return;
+ if (sym->ctype.base_type == &void_type)
+ return;
if (!sym->ident) {
- warn(sym->token, "no identifier for function argument");
+ warn(decl->token, "no identifier for function argument");
return;
}
bind_symbol(sym, sym->ident->ident, NS_SYMBOL);
@@ -659,7 +702,7 @@ static struct token *external_declaration(struct token *token, struct symbol_lis
if (decl->type == SYM_FN && match_op(token, '{')) {
decl->stmt = alloc_statement(token, STMT_COMPOUND);
start_symbol_scope();
- symbol_iterate(decl->arguments, declare_argument, NULL);
+ symbol_iterate(decl->arguments, declare_argument, decl);
token = compound_statement(token->next, decl->stmt);
end_symbol_scope();
return expect(token, '}', "at end of function");
diff --git a/symbol.h b/symbol.h
index 712fb22e..d1e2b154 100644
--- a/symbol.h
+++ b/symbol.h
@@ -42,6 +42,7 @@ enum type {
SYM_TYPEDEF,
SYM_MEMBER,
SYM_BITFIELD,
+ SYM_ELLIPSIS,
};
struct ctype {
diff --git a/test-lexing.c b/test-lexing.c
index 08860019..d186f31b 100644
--- a/test-lexing.c
+++ b/test-lexing.c
@@ -19,6 +19,7 @@ char *includepath[] = {
"/usr/lib/gcc-lib/i386-redhat-linux/3.2.1/include/",
#if 1
"/home/torvalds/v2.5/linux/include/",
+ "/home/torvalds/v2.5/linux/include/asm-i386/mach-default/",
#else
"/usr/include/",
"/usr/local/include/",
diff --git a/test-parsing.c b/test-parsing.c
index d4fc7a4a..ad7ba413 100644
--- a/test-parsing.c
+++ b/test-parsing.c
@@ -22,6 +22,7 @@ char *includepath[] = {
"/usr/lib/gcc-lib/i386-redhat-linux/3.2.1/include/",
#if 1
"/home/torvalds/v2.5/linux/include/",
+ "/home/torvalds/v2.5/linux/include/asm-i386/mach-default/",
#else
"/usr/include/",
"/usr/local/include/",