The following introduces convert_to_complex_nofold, similarly to what I've done with convert_to_pointer. Nothing too surprising in the patch, I suppose.
Now, what remains to do is to also introduce convert_to_real. Then we should be done with convert.c as convert_to_vector doesn't fold and convert_to_fixed isn't used in the C++ FE at all. More tomorrow. Bootstrapped/regtested on x86_64-linux, ok for branch? diff --git gcc/convert.c gcc/convert.c index ab3eb20..ec6ff37 100644 --- gcc/convert.c +++ gcc/convert.c @@ -40,6 +40,9 @@ along with GCC; see the file COPYING3. If not see #define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \ ((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR) \ : build1_loc (LOC, CODE, TYPE, EXPR)) +#define maybe_fold_build2_loc(FOLD_P, LOC, CODE, TYPE, EXPR1, EXPR2) \ + ((FOLD_P) ? fold_build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2) \ + : build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2)) /* Convert EXPR to some pointer or reference type TYPE. EXPR must be pointer, reference, integer, enumeral, or literal zero; @@ -968,11 +971,13 @@ convert_to_integer_nofold (tree type, tree expr) return convert_to_integer_1 (type, expr, CONSTANT_CLASS_P (expr)); } -/* Convert EXPR to the complex type TYPE in the usual ways. */ +/* Convert EXPR to the complex type TYPE in the usual ways. If FOLD_P is + true, try to fold the expression. */ -tree -convert_to_complex (tree type, tree expr) +static tree +convert_to_complex_1 (tree type, tree expr, bool fold_p) { + location_t loc = EXPR_LOCATION (expr); tree subtype = TREE_TYPE (type); switch (TREE_CODE (TREE_TYPE (expr))) @@ -993,43 +998,63 @@ convert_to_complex (tree type, tree expr) return expr; else if (TREE_CODE (expr) == COMPOUND_EXPR) { - tree t = convert_to_complex (type, TREE_OPERAND (expr, 1)); + tree t = convert_to_complex_1 (type, TREE_OPERAND (expr, 1), + fold_p); if (t == TREE_OPERAND (expr, 1)) return expr; return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), TREE_OPERAND (expr, 0), t); - } + } else if (TREE_CODE (expr) == COMPLEX_EXPR) - return fold_build2 (COMPLEX_EXPR, type, - convert (subtype, TREE_OPERAND (expr, 0)), - convert (subtype, TREE_OPERAND (expr, 1))); + return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type, + convert (subtype, + TREE_OPERAND (expr, 0)), + convert (subtype, + TREE_OPERAND (expr, 1))); else { expr = save_expr (expr); - return - fold_build2 (COMPLEX_EXPR, type, - convert (subtype, - fold_build1 (REALPART_EXPR, - TREE_TYPE (TREE_TYPE (expr)), - expr)), - convert (subtype, - fold_build1 (IMAGPART_EXPR, - TREE_TYPE (TREE_TYPE (expr)), - expr))); + tree realp = maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR, + TREE_TYPE (TREE_TYPE (expr)), + expr); + tree imagp = maybe_fold_build1_loc (fold_p, loc, IMAGPART_EXPR, + TREE_TYPE (TREE_TYPE (expr)), + expr); + return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type, + convert (subtype, realp), + convert (subtype, imagp)); } } case POINTER_TYPE: case REFERENCE_TYPE: error ("pointer value used where a complex was expected"); - return convert_to_complex (type, integer_zero_node); + return convert_to_complex_1 (type, integer_zero_node, fold_p); default: error ("aggregate value used where a complex was expected"); - return convert_to_complex (type, integer_zero_node); + return convert_to_complex_1 (type, integer_zero_node, fold_p); } } +/* A wrapper around convert_to_complex_1 that always folds the + expression. */ + +tree +convert_to_complex (tree type, tree expr) +{ + return convert_to_complex_1 (type, expr, true); +} + +/* A wrapper around convert_to_complex_1 that only folds the + expression if it is CONSTANT_CLASS_P. */ + +tree +convert_to_complex_nofold (tree type, tree expr) +{ + return convert_to_complex_1 (type, expr, CONSTANT_CLASS_P (expr)); +} + /* Convert EXPR to the vector type TYPE in the usual ways. */ tree diff --git gcc/convert.h gcc/convert.h index 24fa6bf..6cb439e 100644 --- gcc/convert.h +++ gcc/convert.h @@ -27,6 +27,7 @@ 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); +extern tree convert_to_complex_nofold (tree, tree); extern tree convert_to_vector (tree, tree); #endif /* GCC_CONVERT_H */ diff --git gcc/cp/cvt.c gcc/cp/cvt.c index 04f6b81..1368f15 100644 --- gcc/cp/cvt.c +++ gcc/cp/cvt.c @@ -710,7 +710,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, /* For complex data types, we need to perform componentwise conversion. */ else if (TREE_CODE (type) == COMPLEX_TYPE) - return convert_to_complex (type, e); + return convert_to_complex_nofold (type, e); else if (VECTOR_TYPE_P (type)) return convert_to_vector (type, e); else if (TREE_CODE (e) == TARGET_EXPR) @@ -848,7 +848,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, if (code == REAL_TYPE) return convert_to_real (type, e); else if (code == COMPLEX_TYPE) - return convert_to_complex (type, e); + return convert_to_complex_nofold (type, e); } /* New C++ semantics: since assignment is now based on Marek