aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2010-11-13 09:52:00 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2010-11-13 09:52:00 +0000
commit9e5b21156632fd14bfaeea24919c614e56645989 (patch)
treeeb7240972890ab86d11f88bf6522ea66910f938f
parent18406601136a40c875005c3f11563f657fc1f0ca (diff)
downloadgcc-9e5b21156632fd14bfaeea24919c614e56645989.zip
gcc-9e5b21156632fd14bfaeea24919c614e56645989.tar.gz
gcc-9e5b21156632fd14bfaeea24919c614e56645989.tar.bz2
c-tree.h (enum c_typespec_kind): Add ctsk_none.
2010-11-13 Paolo Bonzini <bonzini@gnu.org> * c-tree.h (enum c_typespec_kind): Add ctsk_none. (struct c_declspecs): Replace tagdef_seen_p and type_seen_p with typespec_kind. * c-decl.c (build_null_declspecs): Initialize typespec_kind. (shadow_tag_warned, check_compound_literal_type): Adjust uses of tag_defined_p. (declspecs_add_type): Set typespec_kind. * c-parser.c (c_parser_declaration_or_fndef, c_parser_declspecs, c_parser_struct_declaration, c_parser_parameter_declaration, c_parser_type_name, c_parser_objc_diagnose_bad_element_prefix): Adjust uses of type_seen_p. * c-typeck.c (c_cast_expr): Use typespec_kind instead of tag_defined_p, pass ctsk_firstref through. testsuite: 2010-11-13 Paolo Bonzini <bonzini@gnu.org> * gcc.dg/Wcxx-compat-8.c: Add testcases involving incomplete types. From-SVN: r166699
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/c-decl.c17
-rw-r--r--gcc/c-parser.c19
-rw-r--r--gcc/c-tree.h11
-rw-r--r--gcc/c-typeck.c5
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/Wcxx-compat-8.c26
7 files changed, 74 insertions, 25 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 44035e3..af43e31 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
2010-11-13 Paolo Bonzini <bonzini@gnu.org>
+ * c-tree.h (enum c_typespec_kind): Add ctsk_none.
+ (struct c_declspecs): Replace tagdef_seen_p and type_seen_p
+ with typespec_kind.
+ * c-decl.c (build_null_declspecs): Initialize typespec_kind.
+ (shadow_tag_warned, check_compound_literal_type): Adjust
+ uses of tag_defined_p.
+ (declspecs_add_type): Set typespec_kind.
+ * c-parser.c (c_parser_declaration_or_fndef,
+ c_parser_declspecs, c_parser_struct_declaration,
+ c_parser_parameter_declaration, c_parser_type_name,
+ c_parser_objc_diagnose_bad_element_prefix): Adjust uses
+ of type_seen_p.
+ * c-typeck.c (c_cast_expr): Use typespec_kind instead of
+ tag_defined_p, pass ctsk_firstref through.
+
+2010-11-13 Paolo Bonzini <bonzini@gnu.org>
+
* c-format.c (enum format_specifier_kind, kind_descriptions): New.
(struct format_wanted_type): Replace field "name" with "kind", add
"format_start" and "format_length".
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index e1f1402..c0d5a49 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3634,7 +3634,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
warned = 1;
}
}
- else if (!declspecs->tag_defined_p
+ else if (declspecs->typespec_kind != ctsk_tagdef
+ && declspecs->typespec_kind != ctsk_tagfirstref
&& declspecs->storage_class != csc_none)
{
if (warned != 1)
@@ -3644,7 +3645,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
warned = 1;
pending_xref_error ();
}
- else if (!declspecs->tag_defined_p
+ else if (declspecs->typespec_kind != ctsk_tagdef
+ && declspecs->typespec_kind != ctsk_tagfirstref
&& (declspecs->const_p
|| declspecs->volatile_p
|| declspecs->restrict_p
@@ -4580,7 +4582,9 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
void
check_compound_literal_type (location_t loc, struct c_type_name *type_name)
{
- if (warn_cxx_compat && type_name->specs->tag_defined_p)
+ if (warn_cxx_compat
+ && (type_name->specs->typespec_kind == ctsk_tagdef
+ || type_name->specs->typespec_kind == ctsk_tagfirstref))
warning_at (loc, OPT_Wc___compat,
"defining a type in a compound literal is invalid in C++");
}
@@ -8616,10 +8620,9 @@ build_null_declspecs (void)
ret->storage_class = csc_none;
ret->expr_const_operands = true;
ret->declspecs_seen_p = false;
- ret->type_seen_p = false;
+ ret->typespec_kind = ctsk_none;
ret->non_sc_seen_p = false;
ret->typedef_p = false;
- ret->tag_defined_p = false;
ret->explicit_signed_p = false;
ret->deprecated_p = false;
ret->default_int_p = false;
@@ -8703,7 +8706,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
tree type = spec.spec;
specs->non_sc_seen_p = true;
specs->declspecs_seen_p = true;
- specs->type_seen_p = true;
+ specs->typespec_kind = spec.kind;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
@@ -9306,8 +9309,6 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
}
else if (TREE_CODE (type) != ERROR_MARK)
{
- if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
- specs->tag_defined_p = true;
if (spec.kind == ctsk_typeof)
{
specs->typedef_p = true;
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 484dab2..9761e4e 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -1462,7 +1462,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
should diagnose if there were no declaration specifiers) or a
function definition (in which case the diagnostic for
implicit int suffices). */
- declarator = c_parser_declarator (parser, specs->type_seen_p,
+ declarator = c_parser_declarator (parser,
+ specs->typespec_kind != ctsk_none,
C_DTR_NORMAL, &dummy);
if (declarator == NULL)
{
@@ -1831,7 +1832,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool scspec_ok, bool typespec_ok, bool start_attr_ok)
{
bool attrs_ok = start_attr_ok;
- bool seen_type = specs->type_seen_p;
+ bool seen_type = specs->typespec_kind != ctsk_none;
while (c_parser_next_token_is (parser, CPP_NAME)
|| c_parser_next_token_is (parser, CPP_KEYWORD)
|| (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
@@ -2399,7 +2400,7 @@ c_parser_struct_declaration (c_parser *parser)
|| c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
tree ret;
- if (!specs->type_seen_p)
+ if (specs->typespec_kind == ctsk_none)
{
pedwarn (decl_loc, OPT_pedantic,
"ISO C forbids member declarations with no members");
@@ -2434,7 +2435,8 @@ c_parser_struct_declaration (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_COLON))
declarator = build_id_declarator (NULL_TREE);
else
- declarator = c_parser_declarator (parser, specs->type_seen_p,
+ declarator = c_parser_declarator (parser,
+ specs->typespec_kind != ctsk_none,
C_DTR_NORMAL, &dummy);
if (declarator == NULL)
{
@@ -3078,7 +3080,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
pending_xref_error ();
prefix_attrs = specs->attrs;
specs->attrs = NULL_TREE;
- declarator = c_parser_declarator (parser, specs->type_seen_p,
+ declarator = c_parser_declarator (parser,
+ specs->typespec_kind != ctsk_none,
C_DTR_PARM, &dummy);
if (declarator == NULL)
{
@@ -3370,7 +3373,8 @@ c_parser_type_name (c_parser *parser)
}
pending_xref_error ();
finish_declspecs (specs);
- declarator = c_parser_declarator (parser, specs->type_seen_p,
+ declarator = c_parser_declarator (parser,
+ specs->typespec_kind != ctsk_none,
C_DTR_ABSTRACT, &dummy);
if (declarator == NULL)
return NULL;
@@ -7618,7 +7622,8 @@ static bool
c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
struct c_declspecs *specs)
{
- if (!specs->declspecs_seen_p || specs->type_seen_p || specs->non_sc_seen_p)
+ if (!specs->declspecs_seen_p || specs->non_sc_seen_p
+ || specs->typespec_kind != ctsk_none)
{
c_parser_error (parser,
"no type or storage class may be specified here,");
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 0d94ceb..0581b38 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -134,6 +134,8 @@ struct c_expr
only used to distinguish tag definitions, tag references and typeof
uses. */
enum c_typespec_kind {
+ /* No typespec. This appears only in struct c_declspec. */
+ ctsk_none,
/* A reserved keyword type specifier. */
ctsk_resword,
/* A reference to a tag, previously declared, such as "struct foo".
@@ -225,13 +227,14 @@ struct c_declspecs {
/* Any type specifier keyword used such as "int", not reflecting
modifiers such as "short", or cts_none if none. */
ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
+ /* The kind of type specifier if one has been seen, ctsk_none
+ otherwise. */
+ ENUM_BITFIELD (c_typespec_kind) typespec_kind : 3;
/* Whether any expressions in typeof specifiers may appear in
constant expressions. */
BOOL_BITFIELD expr_const_operands : 1;
/* Whether any declaration specifiers have been seen at all. */
BOOL_BITFIELD declspecs_seen_p : 1;
- /* Whether a type specifier has been seen. */
- BOOL_BITFIELD type_seen_p : 1;
/* Whether something other than a storage class specifier or
attribute has been seen. This is used to warn for the
obsolescent usage of storage class specifiers other than at the
@@ -241,10 +244,6 @@ struct c_declspecs {
BOOL_BITFIELD non_sc_seen_p : 1;
/* Whether the type is specified by a typedef or typeof name. */
BOOL_BITFIELD typedef_p : 1;
- /* Whether a struct, union or enum type either had its content
- defined by a type specifier in the list or was the first visible
- declaration of its tag. */
- BOOL_BITFIELD tag_defined_p : 1;
/* Whether the type is explicitly "signed" or specified by a typedef
whose type is explicitly "signed". */
BOOL_BITFIELD explicit_signed_p : 1;
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 7f448dd..9018c4e 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -4831,8 +4831,9 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
SET_EXPR_LOCATION (ret, loc);
- /* C++ does not permits types to be defined in a cast. */
- if (warn_cxx_compat && type_name->specs->tag_defined_p)
+ /* C++ does not permits types to be defined in a cast, but it
+ allows references to incomplete types. */
+ if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
warning_at (loc, OPT_Wc___compat,
"defining a type in a cast is invalid in C++");
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ee05b7b..f878023 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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>
+
* gcc.dg/format/few-1.c: New test.
* gcc.dg/format/asm_fprintf-1.c: Adjust.
* gcc.dg/format/c90-scanf-1.c: Adjust.
diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-8.c b/gcc/testsuite/gcc.dg/Wcxx-compat-8.c
index a7343ba..7dad7a4 100644
--- a/gcc/testsuite/gcc.dg/Wcxx-compat-8.c
+++ b/gcc/testsuite/gcc.dg/Wcxx-compat-8.c
@@ -22,7 +22,17 @@ enum e2
struct s3 v3;
int v4 = C;
+enum e3
+{
+ F = sizeof (struct t3), /* { dg-bogus "invalid in C\[+\]\[+\]" } */
+ /* { dg-error "invalid application of 'sizeof'" "" { target *-*-* } 27 } */
+ G = __alignof__ (struct t4), /* { dg-bogus "invalid in C\[+\]\[+\]" } */
+ /* { dg-error "invalid application of '__alignof__'" "" { target *-*-* } 29 } */
+ H
+};
+
__typeof__ (struct s5 { int i; }) v5; /* { dg-warning "invalid in C\[+\]\[+\]" } */
+__typeof__ (struct t5) w5; /* { dg-bogus "invalid in C\[+\]\[+\]" } */
int
f1 (struct s1 *p)
@@ -30,14 +40,26 @@ f1 (struct s1 *p)
return ((struct s6 { int j; } *) p)->j; /* { dg-warning "invalid in C\[+\]\[+\]" } */
}
-int
+void *
f2 (struct s1 *p)
{
+ return ((struct t6 *) p); /* { dg-bogus "invalid in C\[+\]\[+\]" } */
+}
+
+int
+f3 (struct s1 *p)
+{
return (__extension__ (struct s7 { int j; } *)p)->j;
}
int
-f3 ()
+f4 ()
{
return (struct s8 { int i; }) { 0 }.i; /* { dg-warning "invalid in C\[+\]\[+\]" } */
}
+
+void *
+f5 ()
+{
+ return &((struct t8) { }); /* { dg-warning "invalid in C\[+\]\[+\]" } */
+}