c-parser.c (c_token_is_qualifier, [...]): New.

2010-11-17  Paolo Bonzini  <bonzini@gnu.org>

        * c-parser.c (c_token_is_qualifier,
        c_parser_next_token_is_qualifier): New.
        (c_parser_declaration_or_fndef, c_parser_struct_declaration):
        Improve error message on specs->tagdef_seen_p.
        (c_parser_struct_or_union_specifier): Improve error recovery.
        (c_parser_declspecs): Move exit condition on C_ID_ID early.
        Reorganize exit condition for C_ID_TYPENAME/C_ID_CLASSNAME
        using c_parser_next_token_is_qualifier; extend it to cover
        a ctsk_tagdef typespec and !typespec_ok in general.

testsuite:
2010-11-17  Paolo Bonzini  <bonzini@gnu.org>

        * gcc.dg/two-types-1.c: New test.
        * gcc.dg/two-types-2.c: New test.
        * gcc.dg/two-types-3.c: New test.
        * gcc.dg/two-types-4.c: New test.
        * gcc.dg/two-types-5.c: New test.
        * gcc.dg/two-types-6.c: New test.
        * gcc.dg/two-types-7.c: New test.
        * gcc.dg/two-types-8.c: New test.
        * gcc.dg/two-types-9.c: New test.
        * gcc.dg/two-types-10.c: New test.
        * objc.dg/two-types-1.m: New test.

From-SVN: r166874
This commit is contained in:
Paolo Bonzini 2010-11-17 18:17:17 +00:00 committed by Paolo Bonzini
parent 0197bf54a1
commit f725e72170
14 changed files with 206 additions and 8 deletions

View File

@ -1,3 +1,15 @@
2010-11-17 Paolo Bonzini <bonzini@gnu.org>
* c-parser.c (c_token_is_qualifier,
c_parser_next_token_is_qualifier): New.
(c_parser_declaration_or_fndef, c_parser_struct_declaration):
Improve error message on specs->tagdef_seen_p.
(c_parser_struct_or_union_specifier): Improve error recovery.
(c_parser_declspecs): Move exit condition on C_ID_ID early.
Reorganize exit condition for C_ID_TYPENAME/C_ID_CLASSNAME
using c_parser_next_token_is_qualifier; extend it to cover
a ctsk_tagdef typespec and !typespec_ok in general.
2010-11-17 Richard Guenther <rguenther@suse.de>
* value-prof.c (gimple_divmod_fixed_value_transform): Update

View File

@ -506,6 +506,47 @@ c_parser_next_token_starts_typename (c_parser *parser)
return c_token_starts_typename (token);
}
/* Return true if TOKEN is a type qualifier, false otherwise. */
static bool
c_token_is_qualifier (c_token *token)
{
switch (token->type)
{
case CPP_NAME:
switch (token->id_kind)
{
case C_ID_ADDRSPACE:
return true;
default:
return false;
}
case CPP_KEYWORD:
switch (token->keyword)
{
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
return true;
default:
return false;
}
case CPP_LESS:
return false;
default:
gcc_unreachable ();
}
}
/* Return true if the next token from PARSER is a type qualifier,
false otherwise. */
static inline bool
c_parser_next_token_is_qualifier (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
return c_token_is_qualifier (token);
}
/* Return true if TOKEN can start declaration specifiers, false
otherwise. */
static bool
@ -1409,6 +1450,19 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_consume_token (parser);
return;
}
/* Provide better error recovery. Note that a type name here is usually
better diagnosed as a redeclaration. */
if (empty_ok
&& specs->typespec_kind == ctsk_tagdef
&& c_parser_next_token_starts_declspecs (parser)
&& !c_parser_next_token_is (parser, CPP_NAME))
{
c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
parser->error = false;
shadow_tag_warned (specs, 1);
return;
}
else if (c_dialect_objc ())
{
/* Prefix attributes are an error on method decls. */
@ -1872,13 +1926,31 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
{
bool attrs_ok = start_attr_ok;
bool seen_type = specs->typespec_kind != ctsk_none;
while (c_parser_next_token_is (parser, CPP_NAME)
while ((c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_token (parser)->id_kind != C_ID_ID)
|| c_parser_next_token_is (parser, CPP_KEYWORD)
|| (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
{
struct c_typespec t;
tree attrs;
location_t loc = c_parser_peek_token (parser)->location;
if (!c_parser_next_token_is_qualifier (parser))
{
/* Exit for TYPENAMEs after any type because they can appear as a
field name. */
if (seen_type && c_parser_next_token_is (parser, CPP_NAME))
break;
/* If we cannot accept a type, and the next token must start one,
exit. Do the same if we already have seen a tagged definition,
since it would be an error anyway and likely the user has simply
forgotten a semicolon. */
if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
&& c_parser_next_token_starts_typename (parser))
break;
}
if (c_parser_next_token_is (parser, CPP_NAME))
{
tree value = c_parser_peek_token (parser)->value;
@ -1894,12 +1966,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
continue;
}
/* This finishes the specifiers unless a type name is OK, it
is declared as a type name and a type name hasn't yet
been seen. */
if (!typespec_ok || seen_type
|| (kind != C_ID_TYPENAME && kind != C_ID_CLASSNAME))
break;
/* Now at a C_ID_TYPENAME or C_ID_CLASSNAME. */
c_parser_consume_token (parser);
seen_type = true;
attrs_ok = true;
@ -2340,12 +2407,17 @@ c_parser_struct_or_union_specifier (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
pedwarn (c_parser_peek_token (parser)->location, 0,
"no semicolon at end of struct or union");
else
else if (parser->error
|| !c_parser_next_token_starts_declspecs (parser))
{
c_parser_error (parser, "expected %<;%>");
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
break;
}
/* If we come here, we have already emitted an error
for an expected `;', identifier or `(', and we also
recovered already. Go on with the next field. */
}
}
postfix_attrs = c_parser_attributes (parser);
@ -2461,6 +2533,19 @@ c_parser_struct_declaration (c_parser *parser)
}
return ret;
}
/* Provide better error recovery. Note that a type name here is valid,
and will be treated as a field name. */
if (specs->typespec_kind == ctsk_tagdef
&& TREE_CODE (specs->type) != ENUMERAL_TYPE
&& c_parser_next_token_starts_declspecs (parser)
&& !c_parser_next_token_is (parser, CPP_NAME))
{
c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
parser->error = false;
return NULL_TREE;
}
pending_xref_error ();
prefix_attrs = specs->attrs;
all_prefix_attrs = prefix_attrs;

View File

@ -1,3 +1,17 @@
2010-11-17 Paolo Bonzini <bonzini@gnu.org>
* gcc.dg/two-types-1.c: New test.
* gcc.dg/two-types-2.c: New test.
* gcc.dg/two-types-3.c: New test.
* gcc.dg/two-types-4.c: New test.
* gcc.dg/two-types-5.c: New test.
* gcc.dg/two-types-6.c: New test.
* gcc.dg/two-types-7.c: New test.
* gcc.dg/two-types-8.c: New test.
* gcc.dg/two-types-9.c: New test.
* gcc.dg/two-types-10.c: New test.
* objc.dg/two-types-1.m: New test.
2010-11-17 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/46440

View File

@ -0,0 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
typedef int x, y;
x y z; /* { dg-error "" "" } */

View File

@ -0,0 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
typedef enum a { XYZ } a; /* { dg-message "previous declaration" } */
enum a a; /* { dg-error "redeclared" } */
struct b { enum a a : 8; };

View File

@ -0,0 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
typedef int x, y;
x struct f z; /* { dg-error "two or more " "" } */

View File

@ -0,0 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
struct f {
}
int z(); /* { dg-error "expected ';', identifier or " "" { target *-*-* } } */

View File

@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
int f()
{
struct f {
}
int z; /* { dg-error "expected ';', identifier or " "" } */
}

View File

@ -0,0 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
struct f {}
struct g {} /* { dg-error "expected ';', identifier or " "" } */
int f(); /* { dg-error "expected ';', identifier or " "" } */

View File

@ -0,0 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
struct s {
struct f {} /* dg-warning "does not declare anything" "" } */
struct g {} x; /* { dg-error "expected ';', identifier or " "" } */
};

View File

@ -0,0 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
struct s {
struct f {}
enum a { X } /* { dg-error "expected ';', identifier or " "" } */
struct g {} /* { dg-error "expected identifier " "" } */
}; /* { dg-warning "no semicolon" "" } */

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
enum x { XYZ }
struct g { enum x a; }; /* { dg-error "expected ';', identifier or " "" } */
int f(struct g *x)
{
return x->a == XYZ; /* { dg-bogus " has no member " "" } */
}

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
struct f {}
static int a, b; /* { dg-error "expected ';', identifier or " "" } */
int f()
{
return a - b; /* { dg-bogus "invalid operands " "" } */
}

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } // suppress default -pedantic-errors */
@interface foo
struct f {}
struct g { int a; }; /* { dg-error "expected ';', identifier or " "" } */
- (struct f *) a;
- (struct g *) b;
@end
int f(struct g *x)
{
return x->a; /* { dg-bogus " has no member " "" } */
}