re PR c++/8153 (ICE with static const member in class)
authorMark Mitchell <mark@codesourcery.com>
Tue, 10 Dec 2002 07:11:46 +0000 (07:11 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 10 Dec 2002 07:11:46 +0000 (07:11 +0000)
PR c++/8153
PR c++/8036
* NEWS: Document removal of in-class initialization extension for
static data members of non-arithmetic, non-enumeration type.
* decl.c (check_static_variable_definition): Do not allow that
extension.
* decl2.c (grokfield): Do not call digest_init when processing
templates.

PR c++/8153
PR c++/8036
* g++.dg/template/static1.C: New test.
* g++.dg/template/static2.C: New test.
* g++.old-deja/g++.ext/memconst.C: New test.

From-SVN: r59980

gcc/cp/ChangeLog
gcc/cp/NEWS
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/static1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/static2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.ext/memconst.C

index 8d600ac..28bdb17 100644 (file)
@@ -1,3 +1,12 @@
+2002-12-09  Mark Mitchell  <mark@codesourcery.com>
+
+       * NEWS: Document removal of in-class initialization extension for 
+       static data members of non-arithmetic, non-enumeration type.
+       * decl.c (check_static_variable_definition): Do not allow that
+       extension.
+       * decl2.c (grokfield): Do not call digest_init when processing
+       templates.
+
 2002-12-05  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * error.c (dump_expr): Fix format specifier warning.
index 85642b5..36720c6 100644 (file)
@@ -2,6 +2,28 @@
 
 * The "new X = 3" extension has been removed; you must now use "new X(3)".
 
+* G++ no longer allows in-class initializations of static data members
+  that do not have arithmetic or enumeration type.  For example:
+
+    struct S { 
+      static const char* const p = "abc";
+    };
+
+  is no longer accepted.  
+
+  Use the standards-conformant form:
+
+    struct S { 
+      static const char* const p;
+    };
+
+    const char* const S::p = "abc";
+
+  instead.
+
+  (ISO C++ is even stricter; it does not allow in-class
+  initializations of floating-point types.)
+
 *** Changes in GCC 3.1:
 
 * -fhonor-std and -fno-honor-std have been removed. -fno-honor-std was
index d881b83..e68c064 100644 (file)
@@ -9616,10 +9616,10 @@ check_static_variable_definition (decl, type)
      the definition, but not both.  If it appears in the class, the
      member is a member constant.  The file-scope definition is always
      required.  */
-  if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+  if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
     {
       error ("invalid in-class initialization of static data member of non-integral type `%T'",
-               type);
+            type);
       /* If we just return the declaration, crashes will sometimes
         occur.  We therefore return void_type_node, as if this was a
         friend declaration, to cause callers to completely ignore
index 61efb58..248fa2d 100644 (file)
@@ -979,30 +979,32 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
              else
                init = digest_init (TREE_TYPE (value), init, (tree *)0);
            }
-         
-         if (TREE_CODE (init) == CONST_DECL)
-           init = DECL_INITIAL (init);
-         else if (TREE_READONLY_DECL_P (init))
-           init = decl_constant_value (init);
-         else if (TREE_CODE (init) == CONSTRUCTOR)
-           init = digest_init (TREE_TYPE (value), init, (tree *)0);
-         if (init == error_mark_node)
-           /* We must make this look different than `error_mark_node'
-              because `decl_const_value' would mis-interpret it
-              as only meaning that this VAR_DECL is defined.  */
-           init = build1 (NOP_EXPR, TREE_TYPE (value), init);
-         else if (processing_template_decl)
-           ;
-         else if (! TREE_CONSTANT (init))
+
+         if (!processing_template_decl)
            {
-             /* We can allow references to things that are effectively
-                static, since references are initialized with the address.  */
-             if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
-                 || (TREE_STATIC (init) == 0
-                     && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
+             if (TREE_CODE (init) == CONST_DECL)
+               init = DECL_INITIAL (init);
+             else if (TREE_READONLY_DECL_P (init))
+               init = decl_constant_value (init);
+             else if (TREE_CODE (init) == CONSTRUCTOR)
+               init = digest_init (TREE_TYPE (value), init, (tree *)0);
+             if (init == error_mark_node)
+               /* We must make this look different than `error_mark_node'
+                  because `decl_const_value' would mis-interpret it
+                  as only meaning that this VAR_DECL is defined.  */
+               init = build1 (NOP_EXPR, TREE_TYPE (value), init);
+             else if (! TREE_CONSTANT (init))
                {
-                 error ("field initializer is not constant");
-                 init = error_mark_node;
+                 /* We can allow references to things that are effectively
+                    static, since references are initialized with the
+                    address.  */
+                 if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
+                     || (TREE_STATIC (init) == 0
+                         && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
+                   {
+                     error ("field initializer is not constant");
+                     init = error_mark_node;
+                   }
                }
            }
        }
index b74a2a1..ca9c2a6 100644 (file)
@@ -1,3 +1,9 @@
+2002-12-09  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/template/static1.C: New test.
+       * g++.dg/template/static2.C: New test.
+       * g++.old-deja/g++.ext/memconst.C: New test.
+
 2002-12-08  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * g++.dg/special/conpr-2.C: Expect failure on solaris2.
diff --git a/gcc/testsuite/g++.dg/template/static1.C b/gcc/testsuite/g++.dg/template/static1.C
new file mode 100644 (file)
index 0000000..f01d032
--- /dev/null
@@ -0,0 +1,4 @@
+template <typename T> struct A
+{
+  static const int t[1][1]={{0}}; // { dg-error "in-class" }
+};
diff --git a/gcc/testsuite/g++.dg/template/static2.C b/gcc/testsuite/g++.dg/template/static2.C
new file mode 100644 (file)
index 0000000..d18c1a7
--- /dev/null
@@ -0,0 +1,17 @@
+class A;
+
+template<int A::* P>
+class B
+{
+public:
+  static int A::* const p = P; // { dg-error "in-class" }
+};
+
+class A
+{
+public:
+
+int dummy;
+
+B<&A::dummy> d;
+};
index a49d3a0..a47a45c 100644 (file)
@@ -12,7 +12,7 @@ public:
 
 class foo {
 private:
-  static const unsigned char * const dummy_key = (unsigned char*)"ThisIs a dummy!";
+  static const unsigned char * const dummy_key = (unsigned char*)"ThisIs a dummy!"; // { dg-error "in-class" }
 
 public:
     void bar ();