aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-parser.c
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2010-11-13 10:01:33 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2010-11-13 10:01:33 +0000
commit2f413185c295b3cf6baabb576bf05209572bf952 (patch)
tree4fb6150727f97abf234833db07b615d4efb0a5f4 /gcc/c-parser.c
parent9e5b21156632fd14bfaeea24919c614e56645989 (diff)
downloadgcc-2f413185c295b3cf6baabb576bf05209572bf952.zip
gcc-2f413185c295b3cf6baabb576bf05209572bf952.tar.gz
gcc-2f413185c295b3cf6baabb576bf05209572bf952.tar.bz2
[multiple changes]
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. testsuite: 2010-11-13 Paolo Bonzini <bonzini@gnu.org> PR c/20385 * gcc.dg/decl-9.c: New. From-SVN: r166700
Diffstat (limited to 'gcc/c-parser.c')
-rw-r--r--gcc/c-parser.c50
1 files changed, 41 insertions, 9 deletions
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));