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:
parent
2f119dcccd
commit
555551c24b
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
11
gcc/testsuite/g++.dg/lookup/anon6.C
Normal file
11
gcc/testsuite/g++.dg/lookup/anon6.C
Normal 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" }
|
Loading…
Reference in New Issue
Block a user