]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/9649 (ICE in finish_member_declaration at cp/semantics.c:1850 when redeclar...
authorMark Mitchell <mark@codesourcery.com>
Fri, 20 Jun 2003 02:40:37 +0000 (02:40 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 20 Jun 2003 02:40:37 +0000 (02:40 +0000)
PR c++/9649
* cp-tree.h (pushdecl_class_level): Change prototype.
(push_class_level_binding): Likewise.
* decl.c (add_binding): Reject duplicate static data members.
(pushdecl_class_level): Return a value indicating whether or not
the binding was valid.
(push_class_level_binding): Likewise.
* semantics.c (finish_member_declaration): Don't keep invalid
declarations.

PR c++/9649
* g++.dg/template/static4.C: New test.
* g++.old-deja/g++.other/anon7.C: Remove spurious error messages.

From-SVN: r68240

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/static4.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/anon7.C

index 30e01f2d8fd0615d9a4a6d620ee6aa694628e992..ba7bc03346a4c82081e4356f38d4e3e7af555d99 100644 (file)
@@ -1,5 +1,15 @@
 2003-06-19  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/9649
+       * cp-tree.h (pushdecl_class_level): Change prototype.
+       (push_class_level_binding): Likewise.
+       * decl.c (add_binding): Reject duplicate static data members.
+       (pushdecl_class_level): Return a value indicating whether or not
+       the binding was valid.
+       (push_class_level_binding): Likewise.
+       * semantics.c (finish_member_declaration): Don't keep invalid
+       declarations.
+
        PR c++/11041
        * call.c (initialize_reference): Do not use cp_finish_decl to emit
        temporary variables.
index bfb7e0f3e68660a3cffa597a6a8d12be993476cc..6bc6f6f2f38605eed31df1abfc6150ea8c989c4e 100644 (file)
@@ -3638,11 +3638,11 @@ extern int decls_match                          (tree, tree);
 extern int duplicate_decls                     (tree, tree);
 extern tree pushdecl_top_level                 (tree);
 extern tree pushdecl_top_level_and_finish       (tree, tree);
-extern void pushdecl_class_level               (tree);
+extern bool pushdecl_class_level               (tree);
 extern tree pushdecl_namespace_level            (tree);
 extern tree push_using_decl                     (tree, tree);
 extern tree push_using_directive                (tree);
-extern void push_class_level_binding           (tree, tree);
+extern bool push_class_level_binding           (tree, tree);
 extern tree implicitly_declare                 (tree);
 extern tree declare_local_label                 (tree);
 extern tree define_label                       (const char *, int, tree);
index d025a6fba1d35269e958993c3ed6c842e98bb1fb..d73c0d08f996f0f3cf9532da22b5387b376af242 100644 (file)
@@ -964,11 +964,18 @@ add_binding (tree id, tree decl)
         type to which it already refers.  */
     ok = 0;
   /* There can be two block-scope declarations of the same variable,
-     so long as they are `extern' declarations.  */
+     so long as they are `extern' declarations.  However, there cannot
+     be two declarations of the same static data member:
+
+       [class.mem]
+
+       A member shall not be declared twice in the
+       member-specification.  */
   else if (TREE_CODE (decl) == VAR_DECL
           && TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
           && DECL_EXTERNAL (decl)
-          && DECL_EXTERNAL (BINDING_VALUE (binding)))
+          && DECL_EXTERNAL (BINDING_VALUE (binding))
+          && !DECL_CLASS_SCOPE_P (decl))
     {
       duplicate_decls (decl, BINDING_VALUE (binding));
       ok = 0;
@@ -4179,10 +4186,11 @@ pushdecl_top_level_and_finish (tree x, tree init)
 
 /* Make the declaration of X appear in CLASS scope.  */
 
-void
+bool
 pushdecl_class_level (tree x)
 {
   tree name;
+  bool is_valid = true;
 
   timevar_push (TV_NAME_LOOKUP);
   /* Get the name of X.  */
@@ -4193,7 +4201,7 @@ pushdecl_class_level (tree x)
 
   if (name)
     {
-      push_class_level_binding (name, x);
+      is_valid = push_class_level_binding (name, x);
       if (TREE_CODE (x) == TYPE_DECL)
        set_identifier_type_value (name, TREE_TYPE (x));
     }
@@ -4205,9 +4213,16 @@ pushdecl_class_level (tree x)
       tree f;
 
       for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
-       pushdecl_class_level (f);
+       {
+         push_srcloc (DECL_SOURCE_FILE (f), DECL_SOURCE_LINE (f));
+         if (!pushdecl_class_level (f))
+           is_valid = false;
+         pop_srcloc ();
+       }
     }
   timevar_pop (TV_NAME_LOOKUP);
+
+  return is_valid;
 }
 
 /* Enter DECL into the symbol table, if that's appropriate.  Returns
@@ -4239,21 +4254,19 @@ maybe_push_decl (tree decl)
     return pushdecl (decl);
 }
 
-/* Make the declaration(s) of X appear in CLASS scope
-   under the name NAME.  */
+/* Make the declaration(s) of X appear in CLASS scope under the name
+   NAME.  Returns true if the binding is valid.  */
 
-void
+bool
 push_class_level_binding (tree name, tree x)
 {
   cxx_binding *binding;
+
   timevar_push (TV_NAME_LOOKUP);
   /* The class_binding_level will be NULL if x is a template
      parameter name in a member template.  */
   if (!class_binding_level)
-    {
-      timevar_pop (TV_NAME_LOOKUP);
-      return;
-    }
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
 
   /* Make sure that this new member does not have the same name
      as a template parameter.  */
@@ -4303,8 +4316,7 @@ push_class_level_binding (tree name, tree x)
            INHERITED_VALUE_BINDING_P (binding) = 0;
            TREE_TYPE (shadow) = x;
            IDENTIFIER_CLASS_VALUE (name) = x;
-           timevar_pop (TV_NAME_LOOKUP);
-           return;
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
          }
     }
 
@@ -4318,8 +4330,10 @@ push_class_level_binding (tree name, tree x)
       /* Record the value we are binding NAME to so that we can know
         what to pop later.  */
       TREE_TYPE (class_binding_level->class_shadowed) = x;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
     }
-  timevar_pop (TV_NAME_LOOKUP);
+
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
 }
 
 /* Insert another USING_DECL into the current binding level, returning
index b400e4d5a44fc2a83d7a2488bed8423f180bcbec..a95c9575e6bc10347291bc6fb707a095d07c5585 100644 (file)
@@ -1862,8 +1862,6 @@ finish_member_declaration (tree decl)
   if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
     SET_DECL_LANGUAGE (decl, lang_cplusplus);
 
-  maybe_add_class_template_decl_list (current_class_type, decl, /*friend_p=*/0);
-
   /* Put functions on the TYPE_METHODS list and everything else on the
      TYPE_FIELDS list.  Note that these are built up in reverse order.
      We reverse them (to obtain declaration order) in finish_struct.  */
@@ -1876,8 +1874,12 @@ finish_member_declaration (tree decl)
 
       TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
       TYPE_METHODS (current_class_type) = decl;
+
+      maybe_add_class_template_decl_list (current_class_type, decl, 
+                                         /*friend_p=*/0);
     }
-  else
+  /* Enter the DECL into the scope of the class.  */
+  else if (TREE_CODE (decl) == USING_DECL || pushdecl_class_level (decl))
     {
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
         go at the beginning.  The reason is that lookup_field_1
@@ -1905,9 +1907,8 @@ finish_member_declaration (tree decl)
          TYPE_FIELDS (current_class_type) = decl;
        }
 
-      /* Enter the DECL into the scope of the class.  */
-      if (TREE_CODE (decl) != USING_DECL)
-       pushdecl_class_level (decl);
+      maybe_add_class_template_decl_list (current_class_type, decl, 
+                                         /*friend_p=*/0);
     }
 }
 
index dd5c99251abe64ded364383f035e64ae479fa1d1..2b4942c81022db129acb71a269372d844daa67d7 100644 (file)
@@ -1,5 +1,9 @@
 2003-06-19  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/9649
+       * g++.dg/template/static4.C: New test.
+       * g++.old-deja/g++.other/anon7.C: Remove spurious error messages.
+
        PR c++/11041
        * g++.dg/init/ref7.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/template/static4.C b/gcc/testsuite/g++.dg/template/static4.C
new file mode 100644 (file)
index 0000000..c548632
--- /dev/null
@@ -0,0 +1,7 @@
+template <class R>
+struct A {
+  static int _test; // { dg-error "" }
+  static int _test; // { dg-error "" }
+};
+template <class R> int A<R>::_test = 0;
+struct B : public A <int> { };
index 3131c6b34ba3926ff76e1f2c849686cf12691dd9..ebc378005cd7686f23691aefc612ffe8204b5aef 100644 (file)
@@ -11,7 +11,7 @@ struct B {
   int b;       // { dg-error "" } conflicts with previous declaration
   union {
     int b;     // { dg-error "" } duplicate member
-  };           // { dg-error "" } declaration of
+  };
 };
 
 struct C {
@@ -20,5 +20,5 @@ struct C {
   };
   union {
     int c;     // { dg-error "" } duplicate member
-  };           // { dg-error "" } declaration of
+  };
 };