This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 19916
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 2 Mar 2005 09:13:53 -0800
- Subject: C++ PATCH: PR 19916
- Reply-to: mark at codesourcery dot com
This patch fixes PR C++/19916. The initializer_constant_valid_p did
not allow initialization of a pointer-to-member with a differently
cv-qualified initializer. The patch looks much bigger than it really
is, in that I tidied up the code a bit while I was there.
Tested on x86_64-unknown-linux-gnu, applied on the mainline. (And,
shortly, on the 4.0 and 3.4 branches.)
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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 Mark Mitchell <mark@codesourcery.com>
PR c++/19916
* g++.dg/init/ptrmem2.C: New test.
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.477
diff -c -5 -p -r1.477 varasm.c
*** varasm.c 30 Jan 2005 18:27:23 -0000 1.477
--- varasm.c 2 Mar 2005 17:06:44 -0000
*************** initializer_constant_valid_p (tree value
*** 3521,3587 ****
case NON_LVALUE_EXPR:
return initializer_constant_valid_p (TREE_OPERAND (value, 0), 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;
! }
!
! /* 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 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);
break;
case PLUS_EXPR:
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
--- 3521,3585 ----
case NON_LVALUE_EXPR:
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
case CONVERT_EXPR:
case NOP_EXPR:
! {
! 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 (dest_type) && POINTER_TYPE_P (src_type)
! && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
! return initializer_constant_valid_p (src, 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:
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
Index: testsuite/g++.dg/init/ptrmem2.C
===================================================================
RCS file: testsuite/g++.dg/init/ptrmem2.C
diff -N testsuite/g++.dg/init/ptrmem2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/ptrmem2.C 2 Mar 2005 17:06:44 -0000
***************
*** 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;
+ }