re PR c++/19916 (Segmentation fault in __static_initialization_and_destruction_0)
authorMark Mitchell <mark@codesourcery.com>
Wed, 2 Mar 2005 17:13:09 +0000 (17:13 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 2 Mar 2005 17:13:09 +0000 (17:13 +0000)
PR c++/19916
* varasm.c (initializer_constant_valid_p): Allow conversions
between OFFSET_TYPEs.  Tidy.

PR c++/19916
* g++.dg/init/ptrmem2.C: New test.

From-SVN: r95787

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/ptrmem2.C [new file with mode: 0644]
gcc/varasm.c

index fc3b3560d58774e595c34a6385a20c1208dca378..3f8b31e274224c602a841c684132cb3c8badbe2d 100644 (file)
@@ -1,3 +1,9 @@
+2005-03-02  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/19916
+       * varasm.c (initializer_constant_valid_p): Allow conversions
+       between OFFSET_TYPEs.  Tidy.
+
 2005-03-02  Hans-Peter Nilsson  <hp@axis.com>
 
        * config/cris/cris.md ("return"): Remove epilogue delay list
index d72534301c68f514bc8786a01578b4aaa2f28613..5351064c549402163d02067cdc00e8898cb019ab 100644 (file)
@@ -1,3 +1,8 @@
+2005-03-02  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/19916
+       * g++.dg/init/ptrmem2.C: New test.
+
 2005-03-02  Joseph S. Myers  <joseph@codesourcery.com>
 
        PR c/8927
diff --git a/gcc/testsuite/g++.dg/init/ptrmem2.C b/gcc/testsuite/g++.dg/init/ptrmem2.C
new file mode 100644 (file)
index 0000000..54b6921
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/19916
+// { dg-do run }
+
+struct S {
+  char k;
+};
+
+char const volatile S::* const p01 = &S::k;
+int main(void)
+{
+  return  0;
+}
index 12ab1b7b01a74c14b0d5451fff4956e0e817ae33..29ce0486766475d9a7e035f5bfc0e56be11a1a45 100644 (file)
@@ -3523,63 +3523,61 @@ initializer_constant_valid_p (tree value, tree endtype)
 
     case CONVERT_EXPR:
     case NOP_EXPR:
-      /* Allow conversions between pointer types.  */
-      if (POINTER_TYPE_P (TREE_TYPE (value))
-         && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-      /* Allow conversions between real types.  */
-      if (FLOAT_TYPE_P (TREE_TYPE (value))
-         && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-      /* Allow length-preserving conversions between integer types.  */
-      if (INTEGRAL_TYPE_P (TREE_TYPE (value))
-         && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
-         && (TYPE_PRECISION (TREE_TYPE (value))
-             == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-      /* Allow conversions between other integer types only if
-        explicit value.  */
-      if (INTEGRAL_TYPE_P (TREE_TYPE (value))
-         && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
-       {
-         tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                    endtype);
-         if (inner == null_pointer_node)
-           return null_pointer_node;
-         break;
-       }
+      {
+       tree src;
+       tree src_type;
+       tree dest_type;
+
+       src = TREE_OPERAND (value, 0);
+       src_type = TREE_TYPE (src);
+       dest_type = TREE_TYPE (value);
+
+       /* Allow conversions between pointer types, floating-point
+          types, and offset types.  */
+       if ((POINTER_TYPE_P (dest_type) && POINTER_TYPE_P (src_type))
+           || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
+           || (TREE_CODE (dest_type) == OFFSET_TYPE
+               && TREE_CODE (src_type) == OFFSET_TYPE))
+         return initializer_constant_valid_p (src, endtype);
+
+       /* Allow length-preserving conversions between integer types.  */
+       if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
+           && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
+         return initializer_constant_valid_p (src, endtype);
+
+       /* Allow conversions between other integer types only if
+          explicit value.  */
+       if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
+         {
+           tree inner = initializer_constant_valid_p (src, endtype);
+           if (inner == null_pointer_node)
+             return null_pointer_node;
+           break;
+         }
 
-      /* Allow (int) &foo provided int is as wide as a pointer.  */
-      if (INTEGRAL_TYPE_P (TREE_TYPE (value))
-         && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
-         && (TYPE_PRECISION (TREE_TYPE (value))
-             >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                            endtype);
-
-      /* Likewise conversions from int to pointers, but also allow
-        conversions from 0.  */
-      if ((POINTER_TYPE_P (TREE_TYPE (value))
-          || TREE_CODE (TREE_TYPE (value)) == OFFSET_TYPE)
-         && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
-       {
-         if (integer_zerop (TREE_OPERAND (value, 0)))
-           return null_pointer_node;
-         else if (TYPE_PRECISION (TREE_TYPE (value))
-                  <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
-           return initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                endtype);
-       }
+       /* Allow (int) &foo provided int is as wide as a pointer.  */
+       if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
+           && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
+         return initializer_constant_valid_p (src, endtype);
 
-      /* Allow conversions to struct or union types if the value
-        inside is okay.  */
-      if (TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
-         || TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                            endtype);
+       /* Likewise conversions from int to pointers, but also allow
+          conversions from 0.  */
+       if ((POINTER_TYPE_P (dest_type)
+            || TREE_CODE (dest_type) == OFFSET_TYPE)
+           && INTEGRAL_TYPE_P (src_type))
+         {
+           if (integer_zerop (src))
+             return null_pointer_node;
+           else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
+             return initializer_constant_valid_p (src, endtype);
+         }
+
+       /* Allow conversions to struct or union types if the value
+          inside is okay.  */
+       if (TREE_CODE (dest_type) == RECORD_TYPE
+           || TREE_CODE (dest_type) == UNION_TYPE)
+         return initializer_constant_valid_p (src, endtype);
+      }
       break;
 
     case PLUS_EXPR: