Comments
Patch
===================================================================
@@ -642,13 +642,30 @@ c_parser_next_token_starts_declspecs (c_
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);
- 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
@@ -1365,6 +1382,24 @@ c_parser_declaration_or_fndef (c_parser
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)
{
@@ -3927,7 +3962,7 @@ c_parser_compound_statement_nostart (c_p
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);
@@ -4089,9 +4124,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 "
@@ -4685,7 +4718,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,
@@ -9056,7 +9089,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));
This patch improves GCC error detection so that some cases of declarations with unknown type names are detected. This also allows GCC to do better on cascading errors, because the variables that are declared enter the symbol table. Bootstrapped/regtested x86_64-pc-linux-gnu, ok? 2010-10-30 Paolo Bonzini <bonzini@gnu.org> * 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. testsuite: 2010-10-30 Paolo Bonzini <bonzini@gnu.org> * gcc.dg/decl-9.c: New. /* { 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" } */ }