diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2009-03-09 07:10:48 +0000 |
---|---|---|
committer | Christopher Li <sparse@chrisli.org> | 2009-07-17 23:06:23 +0000 |
commit | 09e5867415798fb927b9da830b7dbe908d941596 (patch) | |
tree | e949a198b62c2b8b3f132ec5042647346267d2ff /parse.c | |
parent | Fix braino in which_kind() (diff) | |
download | sparse-09e5867415798fb927b9da830b7dbe908d941596.tar.gz sparse-09e5867415798fb927b9da830b7dbe908d941596.tar.bz2 sparse-09e5867415798fb927b9da830b7dbe908d941596.zip |
Sanitize direct_declarator logics
a) handling of nested declarator does not belong in the loop, for fsck sake
b) functions and arrays don't mix (and functions don't mix with functions)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christopher Li <sparse@chrisli.org>
Diffstat (limited to 'parse.c')
-rw-r--r-- | parse.c | 140 |
1 files changed, 65 insertions, 75 deletions
@@ -1224,13 +1224,8 @@ static struct token *handle_attributes(struct token *token, struct ctype *ctype, return token; } -enum kind { - Nested, Empty, K_R, Proto, Bad_Func, Bad_Nested -}; - -static enum kind which_kind(struct token *token, struct token **p, - struct ident **n, - int dont_nest, int prefer_abstract) +static int is_nested(struct token *token, struct token **p, + int prefer_abstract) { /* * This can be either a parameter list or a grouping. @@ -1245,22 +1240,38 @@ static enum kind which_kind(struct token *token, struct token **p, if (token_type(next) == TOKEN_IDENT) { if (lookup_type(next)) - return (dont_nest || prefer_abstract) ? Proto : Nested; - if (dont_nest) { - /* attributes in the K&R identifier list */ - if (next != token->next) - return Bad_Func; - /* identifier list not in definition; complain */ - if (prefer_abstract) - warning(token->pos, - "identifier list not in definition"); - return K_R; - } - return Nested; + return !prefer_abstract; + return 1; + } + + if (match_op(next, ')') || match_op(next, SPECIAL_ELLIPSIS)) + return 0; + + return 1; +} + +enum kind { + Empty, K_R, Proto, Bad_Func, +}; + +static enum kind which_func(struct token *token, + struct ident **n, + int prefer_abstract) +{ + struct token *next = token->next; + + if (token_type(next) == TOKEN_IDENT) { + if (lookup_type(next)) + return Proto; + /* identifier list not in definition; complain */ + if (prefer_abstract) + warning(token->pos, + "identifier list not in definition"); + return K_R; } if (token_type(next) != TOKEN_SPECIAL) - return !dont_nest ? Bad_Nested : Bad_Func; + return Bad_Func; if (next->special == ')') { /* don't complain about those */ @@ -1278,72 +1289,51 @@ static enum kind which_kind(struct token *token, struct token **p, return Proto; } - return dont_nest ? Bad_Func : Nested; + return Bad_Func; } static struct token *direct_declarator(struct token *token, struct ctype *ctx, struct ident **p, int prefer_abstract) { struct ctype *ctype = ctx; - int dont_nest = 0; + struct token *next; if (p && token_type(token) == TOKEN_IDENT) { *p = token->ident; token = token->next; - dont_nest = 1; + } else if (match_op(token, '(') && + is_nested(token, &next, prefer_abstract)) { + struct symbol *base_type = ctype->base_type; + if (token->next != next) + next = handle_attributes(token->next, ctype, + KW_ATTRIBUTE); + token = declarator(next, ctx, p, prefer_abstract); + token = expect(token, ')', "in nested declarator"); + while (ctype->base_type != base_type) + ctype = &ctype->base_type->ctype; + p = NULL; } - for (;;) { - if (token_type(token) != TOKEN_SPECIAL) - return token; - - if (token->special == '(') { - struct symbol *sym; - struct token *next; - enum kind kind = which_kind(token, &next, p, - dont_nest, prefer_abstract); - - dont_nest = 1; - - if (kind == Nested) { - struct symbol *base_type = ctype->base_type; - if (token->next != next) - next = handle_attributes(token->next, ctype, - KW_ATTRIBUTE); - token = declarator(next, ctx, p, prefer_abstract); - token = expect(token, ')', "in nested declarator"); - while (ctype->base_type != base_type) - ctype = &ctype->base_type->ctype; - p = NULL; - continue; - } - - if (kind == Bad_Nested) { - token = expect(token, ')', "in nested declarator"); - p = NULL; - continue; - } - - /* otherwise we have a function */ - sym = alloc_indirect_symbol(token->pos, ctype, SYM_FN); - 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; - } + if (match_op(token, '(')) { + enum kind kind = which_func(token, p, prefer_abstract); + struct symbol *fn; + fn = alloc_indirect_symbol(token->pos, ctype, SYM_FN); + token = token->next; + if (kind == K_R) + token = identifier_list(token, fn); + else if (kind == Proto) + token = parameter_type_list(token, fn); + token = expect(token, ')', "in function declarator"); + fn->endpos = token->pos; + return token; + } - if (token->special == '[') { - struct symbol *array = alloc_indirect_symbol(token->pos, ctype, SYM_ARRAY); - token = abstract_array_declarator(token->next, array); - token = expect(token, ']', "in abstract_array_declarator"); - array->endpos = token->pos; - ctype = &array->ctype; - dont_nest = 1; - continue; - } - break; + while (match_op(token, '[')) { + struct symbol *array; + array = alloc_indirect_symbol(token->pos, ctype, SYM_ARRAY); + token = abstract_array_declarator(token->next, array); + token = expect(token, ']', "in abstract_array_declarator"); + array->endpos = token->pos; + ctype = &array->ctype; } return token; } @@ -2282,7 +2272,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis /* Just a type declaration? */ if (!ident) { warning(token->pos, "missing identifier in declaration"); - return expect(token, ';', "end of type declaration"); + return expect(token, ';', "at the end of type declaration"); } /* type define declaration? */ |