Commit 4782bd5b by Richard Sandiford Committed by Richard Sandiford

decl.c (duplicate_decls): Don't try to unify an implicit typedef with an explicit one.

	* decl.c (duplicate_decls): Don't try to unify an implicit typedef
	with an explicit one.
	(follow_tag_typedef): New.
	(lookup_tag): Use it to extract the tag of an explicit typedef.
	(xref_tag): Likewise.

From-SVN: r52213
parent e6f64875
2002-04-12 Richard Sandiford <rsandifo@redhat.com>
* decl.c (duplicate_decls): Don't try to unify an implicit typedef
with an explicit one.
(follow_tag_typedef): New.
(lookup_tag): Use it to extract the tag of an explicit typedef.
(xref_tag): Likewise.
2002-04-11 Andrew Haley <aph@redhat.com> 2002-04-11 Andrew Haley <aph@redhat.com>
* typeck.c (type_after_usual_arithmetic_conversions): * typeck.c (type_after_usual_arithmetic_conversions):
......
...@@ -82,6 +82,7 @@ static tree grokfndecl PARAMS ((tree, tree, tree, tree, int, ...@@ -82,6 +82,7 @@ static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
enum overload_flags, tree, enum overload_flags, tree,
tree, int, int, int, int, int, int, tree)); tree, int, int, int, int, int, int, tree));
static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree)); static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree follow_tag_typedef PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree, static tree lookup_tag PARAMS ((enum tree_code, tree,
struct binding_level *, int)); struct binding_level *, int));
static void set_identifier_type_value_with_scope static void set_identifier_type_value_with_scope
...@@ -3426,6 +3427,18 @@ duplicate_decls (newdecl, olddecl) ...@@ -3426,6 +3427,18 @@ duplicate_decls (newdecl, olddecl)
} }
} }
/* Do not merge an implicit typedef with an explicit one. In:
class A;
...
typedef class A A __attribute__ ((foo));
the attribute should apply only to the typedef. */
if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return 0;
/* If new decl is `static' and an `extern' was seen previously, /* If new decl is `static' and an `extern' was seen previously,
warn about it. */ warn about it. */
warn_extern_redeclared_static (newdecl, olddecl); warn_extern_redeclared_static (newdecl, olddecl);
...@@ -5285,6 +5298,45 @@ storetags (tags) ...@@ -5285,6 +5298,45 @@ storetags (tags)
current_binding_level->tags = tags; current_binding_level->tags = tags;
} }
/* Return the type that should be used when TYPE's name is preceded
by a tag such as 'struct' or 'union', or null if the name cannot
be used in this way.
For example, when processing the third line of:
struct A;
typedef struct A A;
struct A;
lookup of A will find the typedef. Given A's typedef, this function
will return the type associated with "struct A". For the tag to be
anything other than TYPE, TYPE must be a typedef whose original type
has the same name and context as TYPE itself.
It is not valid for a typedef of an anonymous type to be used with
an explicit tag:
typedef struct { ... } B;
struct B;
Return null for this case. */
static tree
follow_tag_typedef (type)
tree type;
{
tree original;
original = original_type (type);
if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type)
&& (CP_DECL_CONTEXT (TYPE_NAME (original))
== CP_DECL_CONTEXT (TYPE_NAME (type)))
&& !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original)))
return original;
else
return NULL_TREE;
}
/* Given NAME, an IDENTIFIER_NODE, /* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name. return the structure (or union or enum) definition for that name.
Searches binding levels from BINDING_LEVEL up to the global level. Searches binding levels from BINDING_LEVEL up to the global level.
...@@ -5336,18 +5388,23 @@ lookup_tag (form, name, binding_level, thislevel_only) ...@@ -5336,18 +5388,23 @@ lookup_tag (form, name, binding_level, thislevel_only)
else else
old = BINDING_TYPE (old); old = BINDING_TYPE (old);
/* If it has an original type, it is a typedef, and we if (old)
should not return it. */
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
old = NULL_TREE;
if (old && TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE || TREE_CODE (old) == ENUMERAL_TYPE))
{ {
error ("`%#D' redeclared as %C", old, form); /* We've found something at this binding level. If it is
return NULL_TREE; a typedef, extract the tag it refers to. Lookup fails
if the typedef doesn't refer to a taggable type. */
old = follow_tag_typedef (old);
if (!old)
return NULL_TREE;
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
|| TREE_CODE (old) == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", old, form);
return NULL_TREE;
}
return old;
} }
if (old)
return old;
if (thislevel_only || tail == global_namespace) if (thislevel_only || tail == global_namespace)
return NULL_TREE; return NULL_TREE;
} }
...@@ -12685,7 +12742,6 @@ xref_tag (code_type_node, name, globalize) ...@@ -12685,7 +12742,6 @@ xref_tag (code_type_node, name, globalize)
enum tree_code code; enum tree_code code;
register tree ref, t; register tree ref, t;
struct binding_level *b = current_binding_level; struct binding_level *b = current_binding_level;
int got_type = 0;
tree attributes = NULL_TREE; tree attributes = NULL_TREE;
tree context = NULL_TREE; tree context = NULL_TREE;
...@@ -12722,7 +12778,6 @@ xref_tag (code_type_node, name, globalize) ...@@ -12722,7 +12778,6 @@ xref_tag (code_type_node, name, globalize)
{ {
t = name; t = name;
name = TYPE_IDENTIFIER (t); name = TYPE_IDENTIFIER (t);
got_type = 1;
} }
else else
t = IDENTIFIER_TYPE_VALUE (name); t = IDENTIFIER_TYPE_VALUE (name);
...@@ -12767,18 +12822,20 @@ xref_tag (code_type_node, name, globalize) ...@@ -12767,18 +12822,20 @@ xref_tag (code_type_node, name, globalize)
{ {
if (t) if (t)
{ {
ref = follow_tag_typedef (t);
/* [dcl.type.elab] If the identifier resolves to a /* [dcl.type.elab] If the identifier resolves to a
typedef-name or a template type-parameter, the typedef-name or a template type-parameter, the
elaborated-type-specifier is ill-formed. */ elaborated-type-specifier is ill-formed. */
if (t != TYPE_MAIN_VARIANT (t) if (!ref)
|| (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t))) {
pedwarn ("using typedef-name `%D' after `%s'", pedwarn ("using typedef-name `%D' after `%s'",
TYPE_NAME (t), tag_name (tag_code)); TYPE_NAME (t), tag_name (tag_code));
ref = t;
}
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
error ("using template type parameter `%T' after `%s'", error ("using template type parameter `%T' after `%s'",
t, tag_name (tag_code)); t, tag_name (tag_code));
ref = t;
} }
else else
ref = lookup_tag (code, name, b, 0); ref = lookup_tag (code, name, b, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment