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:
parent
0197bf54a1
commit
f725e72170
@ -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
|
||||
|
101
gcc/c-parser.c
101
gcc/c-parser.c
@ -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;
|
||||
|
@ -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
|
||||
|
5
gcc/testsuite/gcc.dg/two-types-1.c
Normal file
5
gcc/testsuite/gcc.dg/two-types-1.c
Normal 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 "" "" } */
|
6
gcc/testsuite/gcc.dg/two-types-10.c
Normal file
6
gcc/testsuite/gcc.dg/two-types-10.c
Normal 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; };
|
5
gcc/testsuite/gcc.dg/two-types-2.c
Normal file
5
gcc/testsuite/gcc.dg/two-types-2.c
Normal 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 " "" } */
|
6
gcc/testsuite/gcc.dg/two-types-3.c
Normal file
6
gcc/testsuite/gcc.dg/two-types-3.c
Normal 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 *-*-* } } */
|
9
gcc/testsuite/gcc.dg/two-types-4.c
Normal file
9
gcc/testsuite/gcc.dg/two-types-4.c
Normal 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 " "" } */
|
||||
}
|
6
gcc/testsuite/gcc.dg/two-types-5.c
Normal file
6
gcc/testsuite/gcc.dg/two-types-5.c
Normal 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 " "" } */
|
7
gcc/testsuite/gcc.dg/two-types-6.c
Normal file
7
gcc/testsuite/gcc.dg/two-types-6.c
Normal 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 " "" } */
|
||||
};
|
8
gcc/testsuite/gcc.dg/two-types-7.c
Normal file
8
gcc/testsuite/gcc.dg/two-types-7.c
Normal 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" "" } */
|
10
gcc/testsuite/gcc.dg/two-types-8.c
Normal file
10
gcc/testsuite/gcc.dg/two-types-8.c
Normal 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 " "" } */
|
||||
}
|
10
gcc/testsuite/gcc.dg/two-types-9.c
Normal file
10
gcc/testsuite/gcc.dg/two-types-9.c
Normal 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 " "" } */
|
||||
}
|
15
gcc/testsuite/objc.dg/two-types-1.m
Normal file
15
gcc/testsuite/objc.dg/two-types-1.m
Normal 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 " "" } */
|
||||
}
|
Loading…
Reference in New Issue
Block a user