summaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-14 00:34:01 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-14 00:34:01 +0000
commit19702c1d34daddd799073407407ff47a44d0084c (patch)
treed480ea1c4408842eab54602e3d430ca39cc2a0b7 /gcc/c-decl.c
parenta86d7a65a99e943f5cd93f16e1d8b8b9c31ff1b1 (diff)
downloadgcc-19702c1d34daddd799073407407ff47a44d0084c.tar.gz
* c-tree.h (enum c_typespec_kind, struct c_typespec,
parser_xref_tag): New. (struct c_declspecs): Add tag_defined_p. Adjust definition of typedef_p. (declspecs_add_type): Adjust prototypes. * c-parse.in (%union): Add tstype. (typespec_nonattr, typespec_attr, typespec_reserved_nonattr, typespec_reserved_attr, typespec_nonreserved_nonattr, structsp_attr, structsp_nonattr): Change to tstype. Update actions. * c-decl.c (build_null_declspecs): Initialize tag_defined_p. (declspecs_add_type): Update to take struct c_typespec argument. Set tag_defined_p and typedef_p as appropriate. (xref_tag): Rename to parser_xref_tag and replace by wrapper. Update to return struct c_typespec. (shadow_tag_warned): Don't let empty declarations with qualifiers or storage class specifiers redeclare a tag if a previous declaration is visible. testsuite: * gcc.dg/c99-tag-3.c, gcc.dg/declspec-14.c: New tests. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89021 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c64
1 files changed, 55 insertions, 9 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index b548f850dd3..30a154cd996 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2696,8 +2696,6 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
{
bool found_tag = false;
- pending_invalid_xref = 0;
-
if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
{
tree value = declspecs->type;
@@ -2721,8 +2719,29 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
warned = 1;
}
}
+ else if (!declspecs->tag_defined_p
+ && declspecs->storage_class != csc_none)
+ {
+ if (warned != 1)
+ pedwarn ("empty declaration with storage class specifier "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
+ else if (!declspecs->tag_defined_p
+ && (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->restrict_p))
+ {
+ if (warned != 1)
+ pedwarn ("empty declaration with type qualifier "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
else
{
+ pending_invalid_xref = 0;
t = lookup_tag (code, name, 1);
if (t == 0)
@@ -2747,6 +2766,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
warned = 1;
}
+ pending_invalid_xref = 0;
+
if (declspecs->inline_p)
{
error ("%<inline%> in empty declaration");
@@ -4877,11 +4898,13 @@ get_parm_info (bool ellipsis)
}
/* Get the struct, enum or union (CODE says which) with tag NAME.
- Define the tag as a forward-reference if it is not defined. */
+ Define the tag as a forward-reference if it is not defined.
+ Return a c_typespec structure for the type specifier. */
-tree
-xref_tag (enum tree_code code, tree name)
+struct c_typespec
+parser_xref_tag (enum tree_code code, tree name)
{
+ struct c_typespec ret;
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
@@ -4897,8 +4920,12 @@ xref_tag (enum tree_code code, tree name)
this would not work properly if we return the reference found.
(For example, with "struct foo" in an outer scope, "union foo;"
must shadow that tag with a new one of union type.) */
+ ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
if (ref && TREE_CODE (ref) == code)
- return ref;
+ {
+ ret.spec = ref;
+ return ret;
+ }
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
@@ -4921,7 +4948,18 @@ xref_tag (enum tree_code code, tree name)
pushtag (name, ref);
- return ref;
+ ret.spec = ref;
+ return ret;
+}
+
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+ Define the tag as a forward-reference if it is not defined.
+ Return a tree for the type. */
+
+tree
+xref_tag (enum tree_code code, tree name)
+{
+ return parser_xref_tag (code, name).spec;
}
/* Make sure that the tag NAME is defined *in the current scope*
@@ -6643,6 +6681,7 @@ build_null_declspecs (void)
ret->storage_class = csc_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;
@@ -6698,8 +6737,9 @@ declspecs_add_qual (struct c_declspecs *specs, tree qual)
returning SPECS. */
struct c_declspecs *
-declspecs_add_type (struct c_declspecs *specs, tree type)
+declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
{
+ tree type = spec.spec;
specs->non_sc_seen_p = true;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
@@ -6975,7 +7015,13 @@ declspecs_add_type (struct c_declspecs *specs, tree type)
specs->type = TREE_TYPE (t);
}
else if (TREE_CODE (type) != ERROR_MARK)
- specs->type = type;
+ {
+ if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
+ specs->tag_defined_p = true;
+ if (spec.kind == ctsk_typeof)
+ specs->typedef_p = true;
+ specs->type = type;
+ }
return specs;
}