cp-tree.h (DECL_VAR_MARKED_P): Remove.

* cp-tree.h (DECL_VAR_MARKED_P): Remove.
	(DECL_ANON_UNION_VAR_P): New macro.
	* class.c (fixed_type_or_null): Tidy.  Use a hash table, rather
	than DECL_VAR_MARKED_P, to keep track of which variables we have
	seen.
	* decl.c (redeclaration_error_message): Complain about redeclaring
	anonymous union members at namespace scope.
	* decl2.c (build_anon_union_vars): Set DECL_ANON_UNION_VAR_P.
	* g++.dg/lookup/anon6.C: New test.

From-SVN: r125745
This commit is contained in:
Mark Mitchell 2007-06-15 16:58:29 +00:00 committed by Mark Mitchell
parent 2f119dcccd
commit 555551c24b
7 changed files with 80 additions and 24 deletions

View File

@ -1,3 +1,14 @@
2007-06-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (DECL_VAR_MARKED_P): Remove.
(DECL_ANON_UNION_VAR_P): New macro.
* class.c (fixed_type_or_null): Tidy. Use a hash table, rather
than DECL_VAR_MARKED_P, to keep track of which variables we have
seen.
* decl.c (redeclaration_error_message): Complain about redeclaring
anonymous union members at namespace scope.
* decl2.c (build_anon_union_vars): Set DECL_ANON_UNION_VAR_P.
2007-06-14 Geoff Keating <geoffk@apple.com>
* decl2.c (determine_visibility): Ensure that functions with

View File

@ -5244,16 +5244,17 @@ finish_struct (tree t, tree attributes)
before this function is called. */
static tree
fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
fixed_type_or_null (tree instance, int *nonnull, int *cdtorp)
{
#define RECUR(T) fixed_type_or_null((T), nonnull, cdtorp)
switch (TREE_CODE (instance))
{
case INDIRECT_REF:
if (POINTER_TYPE_P (TREE_TYPE (instance)))
return NULL_TREE;
else
return fixed_type_or_null (TREE_OPERAND (instance, 0),
nonnull, cdtorp);
return RECUR (TREE_OPERAND (instance, 0));
case CALL_EXPR:
/* This is a call to a constructor, hence it's never zero. */
@ -5273,20 +5274,21 @@ fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
*nonnull = 1;
return TREE_TYPE (instance);
}
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return RECUR (TREE_OPERAND (instance, 0));
case PLUS_EXPR:
case MINUS_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return RECUR (TREE_OPERAND (instance, 0));
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return RECUR (TREE_OPERAND (instance, 0));
return NULL_TREE;
case NOP_EXPR:
case CONVERT_EXPR:
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return RECUR (TREE_OPERAND (instance, 0));
case ADDR_EXPR:
instance = TREE_OPERAND (instance, 0);
@ -5299,14 +5301,14 @@ fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
if (t && DECL_P (t))
*nonnull = 1;
}
return fixed_type_or_null (instance, nonnull, cdtorp);
return RECUR (instance);
case COMPONENT_REF:
/* If this component is really a base class reference, then the field
itself isn't definitive. */
if (DECL_FIELD_IS_BASE (TREE_OPERAND (instance, 1)))
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp);
return RECUR (TREE_OPERAND (instance, 0));
return RECUR (TREE_OPERAND (instance, 1));
case VAR_DECL:
case FIELD_DECL:
@ -5344,22 +5346,33 @@ fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
}
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
{
/* We only need one hash table because it is always left empty. */
static htab_t ht;
if (!ht)
ht = htab_create (37,
htab_hash_pointer,
htab_eq_pointer,
/*htab_del=*/NULL);
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
/* DECL_VAR_MARKED_P is used to prevent recursion; a
/* Enter the INSTANCE in a table to prevent recursion; a
variable's initializer may refer to the variable
itself. */
if (TREE_CODE (instance) == VAR_DECL
&& DECL_INITIAL (instance)
&& !DECL_VAR_MARKED_P (instance))
&& !htab_find (ht, instance))
{
tree type;
DECL_VAR_MARKED_P (instance) = 1;
type = fixed_type_or_null (DECL_INITIAL (instance),
nonnull, cdtorp);
DECL_VAR_MARKED_P (instance) = 0;
void **slot;
slot = htab_find_slot (ht, instance, INSERT);
*slot = instance;
type = RECUR (DECL_INITIAL (instance));
htab_clear_slot (ht, slot);
return type;
}
}
@ -5368,6 +5381,7 @@ fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
default:
return NULL_TREE;
}
#undef RECUR
}
/* Return nonzero if the dynamic type of INSTANCE is known, and
@ -5389,7 +5403,6 @@ resolves_to_fixed_type_p (tree instance, int* nonnull)
{
tree t = TREE_TYPE (instance);
int cdtorp = 0;
tree fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
if (fixed == NULL_TREE)
return 0;

View File

@ -110,7 +110,7 @@ struct diagnostic_context;
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
4: DECL_C_BIT_FIELD (in a FIELD_DECL)
DECL_VAR_MARKED_P (in a VAR_DECL)
DECL_ANON_UNION_VAR_P (in a VAR_DECL)
DECL_SELF_REFERENCE_P (in a TYPE_DECL)
DECL_INVALID_OVERRIDER_P (in a FUNCTION_DECL)
5: DECL_INTERFACE_KNOWN.
@ -2207,10 +2207,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
->decl_flags.u.template_info)
/* For a VAR_DECL, indicates that the variable has been processed.
This flag is set and unset throughout the code; it is always
used for a temporary purpose. */
#define DECL_VAR_MARKED_P(NODE) \
/* For a VAR_DECL, indicates that the variable is actually a
non-static data member of anonymous union that has been promoted to
variable status. */
#define DECL_ANON_UNION_VAR_P(NODE) \
(DECL_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)))
/* Template information for a RECORD_TYPE or UNION_TYPE. */

View File

@ -2187,8 +2187,24 @@ redeclaration_error_message (tree newdecl, tree olddecl)
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
/* The objects have been declared at namespace scope. If either
is a member of an anonymous union, then this is an invalid
redeclaration. For example:
int i;
union { int i; };
is invalid. */
if (DECL_ANON_UNION_VAR_P (newdecl)
|| DECL_ANON_UNION_VAR_P (olddecl))
return "redeclaration of %q#D";
/* If at least one declaration is a reference, there is no
conflict. For example:
int i = 3;
extern int i;
is valid. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return NULL;
/* Reject two definitions. */

View File

@ -1057,6 +1057,7 @@ build_anon_union_vars (tree type, tree object)
tree base;
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
DECL_ANON_UNION_VAR_P (decl) = 1;
base = get_base_address (object);
TREE_PUBLIC (decl) = TREE_PUBLIC (base);

View File

@ -1,3 +1,7 @@
2007-06-15 Mark Mitchell <mark@codesourcery.com>
* g++.dg/lookup/anon6.C: New test.
2007-06-14 Dirk Mueller <dmueller@suse.de>
PR c++/31806

View File

@ -0,0 +1,11 @@
extern int v1; // { dg-error "declared" }
static union { int v1; }; // { dg-error "redeclaration" }
static union { int v2; }; // { dg-error "declared" }
extern int v2; // { dg-error "redeclaration" }
int v3; // { dg-error "declared" }
static union { int v3; }; // { dg-error "redeclaration" }
static union { int v4; }; // { dg-error "declared" }
static union { int v4; }; // { dg-error "redeclaration" }