[backport from gcc-4.8/trunk r190840, adjusted for different location of c-convert.c ] gcc/ 2012-08-31 Jakub Jelinek PR c/54428 * c-convert.c (convert): Don't call fold_convert_loc if TYPE_MAIN_VARIANT of a COMPLEX_TYPE is the same, unless e is a COMPLEX_EXPR. Remove TYPE_MAIN_VARIANT check from COMPLEX_TYPE -> COMPLEX_TYPE conversion. gcc/testsuite/ 2012-08-31 Jakub Jelinek PR c/54428 * gcc.c-torture/compile/pr54428.c: New test. --- gcc-4.7.1/gcc/c-convert.c.~1~ 2011-01-06 11:37:02.000000000 +0100 +++ gcc-4.7.1/gcc/c-convert.c 2012-09-01 13:43:24.000000000 +0200 @@ -92,7 +92,9 @@ convert (tree type, tree expr) STRIP_TYPE_NOPS (e); - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)) + && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE + || TREE_CODE (e) == COMPLEX_EXPR)) return fold_convert_loc (loc, type, expr); if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; @@ -135,24 +137,23 @@ convert (tree type, tree expr) but for the C FE c_save_expr needs to be called instead. */ if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE) { - tree subtype = TREE_TYPE (type); - tree elt_type = TREE_TYPE (TREE_TYPE (e)); - - if (TYPE_MAIN_VARIANT (elt_type) != TYPE_MAIN_VARIANT (subtype) - && TREE_CODE (e) != COMPLEX_EXPR) + if (TREE_CODE (e) != COMPLEX_EXPR) { + tree subtype = TREE_TYPE (type); + tree elt_type = TREE_TYPE (TREE_TYPE (e)); + if (in_late_binary_op) e = save_expr (e); else e = c_save_expr (e); ret - = fold_build2 (COMPLEX_EXPR, type, - convert (subtype, - fold_build1 (REALPART_EXPR, - elt_type, e)), - convert (subtype, - fold_build1 (IMAGPART_EXPR, - elt_type, e))); + = fold_build2_loc (loc, COMPLEX_EXPR, type, + convert (subtype, + fold_build1 (REALPART_EXPR, + elt_type, e)), + convert (subtype, + fold_build1 (IMAGPART_EXPR, + elt_type, e))); goto maybe_fold; } } --- gcc-4.7.1/gcc/testsuite/gcc.c-torture/compile/pr54428.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.7.1/gcc/testsuite/gcc.c-torture/compile/pr54428.c 2012-09-01 13:43:28.000000000 +0200 @@ -0,0 +1,9 @@ +/* PR c/54428 */ + +typedef double _Complex C; + +C +foo (C x, C y, double z, C w) +{ + return y - z * __builtin_cpow (x, 75) * w; +}