diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-15 16:58:29 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-15 16:58:29 +0000 |
commit | 8b2afb7af5b6899d2f63fe0b1013bf0ae45c09ed (patch) | |
tree | b580e5336b6a72d59b683347c5293fe4228f6485 /gcc/cp | |
parent | c388b73aac36fa22b130b88fbc4b1a91c9a7c801 (diff) | |
download | gcc-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/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/class.c | 47 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/decl.c | 20 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 1 |
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); |