summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-15 16:58:29 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-15 16:58:29 +0000
commit8b2afb7af5b6899d2f63fe0b1013bf0ae45c09ed (patch)
treeb580e5336b6a72d59b683347c5293fe4228f6485 /gcc/cp
parentc388b73aac36fa22b130b88fbc4b1a91c9a7c801 (diff)
downloadgcc-8b2afb7af5b6899d2f63fe0b1013bf0ae45c09ed.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125745 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/class.c47
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/decl.c20
-rw-r--r--gcc/cp/decl2.c1
5 files changed, 65 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 17cb3187353..2eeff3ce272 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 953cdffca7d..0314df3adc3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7afc68b06ba..654e25809b1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f7a9f1ec547..33f1c2a311a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 61decb16637..52953b2fa0c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);