[1/18] Leave applying attributes until we know whether it's a nested declarator
diff mbox

Message ID E1LgZcv-0000rB-WF@ZenIV.linux.org.uk
State Mainlined, archived
Headers show

Commit Message

Al Viro March 9, 2009, 7:10 a.m. UTC
Don't mess with applying attributes in which_kind(); leave that until
we know whether that's function declarator or a nested one.  We'll need
that to deal with scopes properly.  Clean parameter_type_list() and
parameter_declaration(), get rid of a leak.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 parse.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 63 insertions(+), 23 deletions(-)

Patch
diff mbox

diff --git a/parse.c b/parse.c
index 73280b4..d70166a 100644
--- a/parse.c
+++ b/parse.c
@@ -1151,10 +1151,60 @@  static struct token *abstract_array_declarator(struct token *token, struct symbo
 	return token;
 }
 
-static struct token *parameter_type_list(struct token *, struct symbol *, struct ctype *);
+static struct token *parameter_type_list(struct token *, struct symbol *);
 static struct token *identifier_list(struct token *, struct symbol *);
 static struct token *declarator(struct token *token, struct symbol *sym, struct ident **p, int);
 
+static struct token *skip_attribute(struct token *token)
+{
+	token = token->next;
+	if (match_op(token, '(')) {
+		int depth = 1;
+		token = token->next;
+		while (depth && !eof_token(token)) {
+			if (token_type(token) == TOKEN_SPECIAL) {
+				if (token->special == '(')
+					depth++;
+				else if (token->special == ')')
+					depth--;
+			}
+			token = token->next;
+		}
+	}
+	return token;
+}
+
+static struct token *skip_attributes(struct token *token)
+{
+	struct symbol *keyword;
+	for (;;) {
+		if (token_type(token) != TOKEN_IDENT)
+			break;
+		keyword = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF);
+		if (!keyword || keyword->type != SYM_KEYWORD)
+			break;
+		if (!(keyword->op->type & KW_ATTRIBUTE))
+			break;
+		token = expect(token->next, '(', "after attribute");
+		token = expect(token, '(', "after attribute");
+		for (;;) {
+			if (eof_token(token))
+				break;
+			if (match_op(token, ';'))
+				break;
+			if (token_type(token) != TOKEN_IDENT)
+				break;
+			token = skip_attribute(token);
+			if (!match_op(token, ','))
+				break;
+			token = token->next;
+		}
+		token = expect(token, ')', "after attribute");
+		token = expect(token, ')', "after attribute");
+	}
+	return token;
+}
+
 static struct token *handle_attributes(struct token *token, struct ctype *ctype, unsigned int keywords)
 {
 	struct symbol *keyword;
@@ -1179,7 +1229,7 @@  enum kind {
 };
 
 static enum kind which_kind(struct token *token, struct token **p,
-			    struct ident **n, struct ctype *ctype,
+			    struct ident **n,
 			    int dont_nest, int prefer_abstract)
 {
 	/*
@@ -1191,7 +1241,7 @@  static enum kind which_kind(struct token *token, struct token **p,
 	 */
 	struct token *next = token->next;
 
-	*p = next = handle_attributes(next, ctype, KW_ATTRIBUTE);
+	*p = next = skip_attributes(next);
 
 	if (token_type(next) == TOKEN_IDENT) {
 		if (lookup_type(next))
@@ -1249,8 +1299,7 @@  static struct token *direct_declarator(struct token *token, struct symbol *decl,
 		if (token->special == '(') {
 			struct symbol *sym;
 			struct token *next;
-			struct ctype thistype = {0, };
-			enum kind kind = which_kind(token, &next, p, &thistype,
+			enum kind kind = which_kind(token, &next, p,
 						dont_nest, prefer_abstract);
 
 			dont_nest = 1;
@@ -1258,7 +1307,8 @@  static struct token *direct_declarator(struct token *token, struct symbol *decl,
 			if (kind == Nested) {
 				struct symbol *base_type = ctype->base_type;
 				if (token->next != next)
-					apply_ctype(token->pos, &thistype, ctype);
+					next = handle_attributes(token->next, ctype,
+								  KW_ATTRIBUTE);
 				token = declarator(next, decl, p, prefer_abstract);
 				token = expect(token, ')', "in nested declarator");
 				while (ctype->base_type != base_type)
@@ -1275,13 +1325,10 @@  static struct token *direct_declarator(struct token *token, struct symbol *decl,
 
 			/* otherwise we have a function */
 			sym = alloc_indirect_symbol(token->pos, ctype, SYM_FN);
-			if (kind == K_R) {
-				next = identifier_list(next, sym);
-			} else if (kind == Proto) {
-				struct ctype *t;
-				t = (token->next == next ? NULL : &thistype);
-				next = parameter_type_list(next, sym, t);
-			}
+			if (kind == K_R)
+				next = identifier_list(token->next, sym);
+			else if (kind == Proto)
+				next = parameter_type_list(token->next, sym);
 			token = expect(next, ')', "in function declarator");
 			sym->endpos = token->pos;
 			continue;
@@ -1425,18 +1472,13 @@  static struct token *struct_declaration_list(struct token *token, struct symbol_
 	return token;
 }
 
-static struct token *parameter_declaration(struct token *token, struct symbol **tree, struct ctype *pending)
+static struct token *parameter_declaration(struct token *token, struct symbol *sym)
 {
 	struct ident *ident = NULL;
-	struct symbol *sym;
 	struct ctype ctype = {0, };
 
-	if (pending)
-		apply_ctype(token->pos, pending, &ctype);
 	token = declaration_specifiers(token, &ctype, 0);
-	sym = alloc_symbol(token->pos, SYM_NODE);
 	sym->ctype = ctype;
-	*tree = sym;
 	token = declarator(token, sym, &ident, 1);
 	token = handle_attributes(token, &sym->ctype, KW_ATTRIBUTE);
 	sym->ident = ident;
@@ -1910,7 +1952,7 @@  static struct token *identifier_list(struct token *token, struct symbol *fn)
 	return token;
 }
 
-static struct token *parameter_type_list(struct token *token, struct symbol *fn, struct ctype *pending)
+static struct token *parameter_type_list(struct token *token, struct symbol *fn)
 {
 	struct symbol_list **list = &fn->arguments;
 
@@ -1924,7 +1966,7 @@  static struct token *parameter_type_list(struct token *token, struct symbol *fn,
 		}
 
 		sym = alloc_symbol(token->pos, SYM_NODE);
-		token = parameter_declaration(token, &sym, pending);
+		token = parameter_declaration(token, sym);
 		if (sym->ctype.base_type == &void_ctype) {
 			/* Special case: (void) */
 			if (!*list && !sym->ident)
@@ -1932,11 +1974,9 @@  static struct token *parameter_type_list(struct token *token, struct symbol *fn,
 			warning(token->pos, "void parameter");
 		}
 		add_symbol(list, sym);
-		sym->endpos = token->pos;
 		if (!match_op(token, ','))
 			break;
 		token = token->next;
-		pending = NULL;
 	}
 	return token;
 }