summaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2005-03-02 17:13:09 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2005-03-02 17:13:09 +0000
commit67f29ece235185d13839c87bd3c5c0a93a2a14fb (patch)
tree80fbf71bf5886e6e3f2c8d0c427f13ed3863b027 /gcc/varasm.c
parent633e8ff53ada380e466146c35e1c96e503209554 (diff)
downloadgcc-67f29ece235185d13839c87bd3c5c0a93a2a14fb.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95787 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c108
1 files changed, 53 insertions, 55 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 12ab1b7b01a..29ce0486766 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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: