This patch introduces convert_to_pointer_nofold; a variant that only folds CONSTANT_CLASS_P expressions. In the C++ FE, convert_to_pointer was only used in cp_convert_to_pointer which is only used in cp_convert. Instead of introducing many _nofold variants, I just made cp_convert_to_pointer use the convert_to_pointer_nofold.
Bootstrapped/regtested on x86_64-linux, ok for branch? diff --git gcc/convert.c gcc/convert.c index 1ce8099..79b4138 100644 --- gcc/convert.c +++ gcc/convert.c @@ -39,10 +39,11 @@ along with GCC; see the file COPYING3. If not see /* Convert EXPR to some pointer or reference type TYPE. EXPR must be pointer, reference, integer, enumeral, or literal zero; - in other cases error is called. */ + in other cases error is called. If FOLD_P is true, try to fold the + expression. */ -tree -convert_to_pointer (tree type, tree expr) +static tree +convert_to_pointer_1 (tree type, tree expr, bool fold_p) { location_t loc = EXPR_LOCATION (expr); if (TREE_TYPE (expr) == type) @@ -58,10 +59,21 @@ convert_to_pointer (tree type, tree expr) addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (type)); addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr))); - if (to_as == from_as) - return fold_build1_loc (loc, NOP_EXPR, type, expr); + if (fold_p) + { + if (to_as == from_as) + return fold_build1_loc (loc, NOP_EXPR, type, expr); + else + return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, + expr); + } else - return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr); + { + if (to_as == from_as) + return build1_loc (loc, NOP_EXPR, type, expr); + else + return build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr); + } } case INTEGER_TYPE: @@ -75,20 +87,43 @@ convert_to_pointer (tree type, tree expr) unsigned int pprec = TYPE_PRECISION (type); unsigned int eprec = TYPE_PRECISION (TREE_TYPE (expr)); - if (eprec != pprec) - expr = fold_build1_loc (loc, NOP_EXPR, - lang_hooks.types.type_for_size (pprec, 0), - expr); + if (eprec != pprec) + { + tree totype = lang_hooks.types.type_for_size (pprec, 0); + if (fold_p) + expr = fold_build1_loc (loc, NOP_EXPR, totype, expr); + else + expr = build1_loc (loc, NOP_EXPR, totype, expr); + } } - return fold_build1_loc (loc, CONVERT_EXPR, type, expr); + if (fold_p) + return fold_build1_loc (loc, CONVERT_EXPR, type, expr); + return build1_loc (loc, CONVERT_EXPR, type, expr); default: error ("cannot convert to a pointer type"); - return convert_to_pointer (type, integer_zero_node); + return convert_to_pointer_1 (type, integer_zero_node, fold_p); } } +/* A wrapper around convert_to_pointer_1 that always folds the + expression. */ + +tree +convert_to_pointer (tree type, tree expr) +{ + return convert_to_pointer_1 (type, expr, true); +} + +/* A wrapper around convert_to_pointer_1 that only folds the + expression if it is CONSTANT_CLASS_P. */ + +tree +convert_to_pointer_nofold (tree type, tree expr) +{ + return convert_to_pointer_1 (type, expr, CONSTANT_CLASS_P (expr)); +} /* Convert EXPR to some floating-point type TYPE. diff --git gcc/convert.h gcc/convert.h index ac78f95..24fa6bf 100644 --- gcc/convert.h +++ gcc/convert.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see extern tree convert_to_integer (tree, tree); extern tree convert_to_integer_nofold (tree, tree); extern tree convert_to_pointer (tree, tree); +extern tree convert_to_pointer_nofold (tree, tree); extern tree convert_to_real (tree, tree); extern tree convert_to_fixed (tree, tree); extern tree convert_to_complex (tree, tree); diff --git gcc/cp/cvt.c gcc/cp/cvt.c index 0a30270..cb73bb7 100644 --- gcc/cp/cvt.c +++ gcc/cp/cvt.c @@ -241,7 +241,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))) == GET_MODE_SIZE (TYPE_MODE (type))); - return convert_to_pointer (type, expr); + return convert_to_pointer_nofold (type, expr); } if (type_unknown_p (expr)) Marek