OSDN Git Service

* cp-tree.h (DECL_VAR_MARKED_P): Remove.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Jun 2007 16:58:29 +0000 (16:58 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Jun 2007 16:58:29 +0000 (16:58 +0000)
(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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/anon6.C [new file with mode: 0644]

index 17cb318..2eeff3c 100644 (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
index 953cdff..0314df3 100644 (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;
index 7afc68b..654e258 100644 (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.  */
index f7a9f1e..33f1c2a 100644 (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.  */
index 61decb1..52953b2 100644 (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);
index 48163ba..7c6d20d 100644 (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
diff --git a/gcc/testsuite/g++.dg/lookup/anon6.C b/gcc/testsuite/g++.dg/lookup/anon6.C
new file mode 100644 (file)
index 0000000..09fa7f8
--- /dev/null
@@ -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" }