diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/c-parser.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/decl-9.c | 32 |
4 files changed, 89 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af43e31..4a036dc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2010-10-30 Paolo Bonzini <bonzini@gnu.org> + + PR c/20385 + * c-parser.c (c_parser_next_token_starts_declaration): Rename to... + (c_parser_next_tokens_start_declaration): ... this. Handle 2nd + token lookahead. + (c_parser_compound_statement_nostart, c_parser_label, + c_parser_for_statement, c_parser_omp_for_loop): Adjust calls. + (c_parser_declaration_or_fndef): Detect the case now matched by + c_parser_next_tokens_start_declaration, give error and correct it. + 2010-11-13 Paolo Bonzini <bonzini@gnu.org> * c-tree.h (enum c_typespec_kind): Add ctsk_none. diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 9761e4e..e5ec2d9 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -614,10 +614,10 @@ c_parser_next_token_starts_declspecs (c_parser *parser) return c_token_starts_declspecs (token); } -/* Return true if the next token from PARSER can start declaration +/* Return true if the next tokens from PARSER can start declaration specifiers or a static assertion, false otherwise. */ static inline bool -c_parser_next_token_starts_declaration (c_parser *parser) +c_parser_next_tokens_start_declaration (c_parser *parser) { c_token *token = c_parser_peek_token (parser); @@ -628,7 +628,23 @@ c_parser_next_token_starts_declaration (c_parser *parser) && c_parser_peek_2nd_token (parser)->type == CPP_DOT) return false; - return c_token_starts_declaration (token); + /* Labels do not start declarations. */ + if (token->type == CPP_NAME + && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + return false; + + if (c_token_starts_declaration (token)) + return true; + + /* Try a bit harder to detect an unknown typename. */ + if (token->type == CPP_NAME + && token->id_kind == C_ID_ID + && (c_parser_peek_2nd_token (parser)->type == CPP_NAME + || c_parser_peek_2nd_token (parser)->type == CPP_MULT) + && !lookup_name (token->value)) + return true; + + return false; } /* Return a pointer to the next-but-one token from PARSER, reading it @@ -1345,6 +1361,24 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, return; } specs = build_null_declspecs (); + + /* Try to detect an unknown type name when we have "A B" or "A *B". */ + if (c_parser_peek_token (parser)->type == CPP_NAME + && c_parser_peek_token (parser)->id_kind == C_ID_ID + && (c_parser_peek_2nd_token (parser)->type == CPP_NAME + || c_parser_peek_2nd_token (parser)->type == CPP_MULT) + && (!nested || !lookup_name (c_parser_peek_token (parser)->value))) + { + error_at (here, "unknown type name %qE", + c_parser_peek_token (parser)->value); + + /* Parse declspecs normally to get a correct pointer type, but avoid + a further "fails to be a type name" error. */ + c_parser_peek_token (parser)->type = CPP_KEYWORD; + c_parser_peek_token (parser)->keyword = RID_VOID; + c_parser_peek_token (parser)->value = error_mark_node; + } + c_parser_declspecs (parser, specs, true, true, start_attr_ok); if (parser->error) { @@ -3868,7 +3902,7 @@ c_parser_compound_statement_nostart (c_parser *parser) c_parser_label (parser); } else if (!last_label - && c_parser_next_token_starts_declaration (parser)) + && c_parser_next_tokens_start_declaration (parser)) { last_label = false; mark_valid_location_for_stdc_pragma (false); @@ -4030,9 +4064,7 @@ c_parser_label (c_parser *parser) } if (label) { - if (c_parser_next_token_starts_declaration (parser) - && !(c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + if (c_parser_next_tokens_start_declaration (parser)) { error_at (c_parser_peek_token (parser)->location, "a label can only be part of a statement and " @@ -4626,7 +4658,7 @@ c_parser_for_statement (c_parser *parser) c_parser_consume_token (parser); c_finish_expr_stmt (loc, NULL_TREE); } - else if (c_parser_next_token_starts_declaration (parser)) + else if (c_parser_next_tokens_start_declaration (parser)) { parser->objc_could_be_foreach_context = true; c_parser_declaration_or_fndef (parser, true, true, true, true, true, @@ -9010,7 +9042,7 @@ c_parser_omp_for_loop (location_t loc, goto pop_scopes; /* Parse the initialization declaration or expression. */ - if (c_parser_next_token_starts_declaration (parser)) + if (c_parser_next_tokens_start_declaration (parser)) { if (i > 0) VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f878023..a2d1a56 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2010-11-13 Paolo Bonzini <bonzini@gnu.org> + PR c/20385 + * gcc.dg/decl-9.c: New. + +2010-11-13 Paolo Bonzini <bonzini@gnu.org> + * gcc.dg/Wcxx-compat-8.c: Add testcases involving incomplete types. 2010-11-13 Paolo Bonzini <bonzini@gnu.org> diff --git a/gcc/testsuite/gcc.dg/decl-9.c b/gcc/testsuite/gcc.dg/decl-9.c new file mode 100644 index 0000000..cc23b07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/decl-9.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu89" } */ + +w *x; /* { dg-error "unknown type name 'w'" } */ + +int z; /* { dg-message "previous declaration of 'z'" } */ +y /* { dg-error "unknown type name 'y'" } */ + * z; /* { dg-error "conflicting " } */ + +int f1() +{ + int d, e; + d * e; /* { dg-bogus "unknown type name 'd'" } */ + g * h; /* { dg-error "unknown type name 'g'" } */ + g i; /* { dg-error "unknown type name 'g'" } */ +} + +typedef int a; + +int f2() +{ +b: a: ; /* { dg-bogus "a label can only be part of a statement" } */ +c: d e; /* { dg-error "a label can only be part of a statement" } */ +/* { dg-error "unknown type name 'd'" "" { target *-*-* } 23 } */ + ; +} + +void *f3() +{ + return x; /* { dg-bogus "'x' undeclared" } */ +} + |