diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d0ba9426b2a..5fab821eb76 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-11-05 Eric Botcazou + + PR tree-optimization/54986 + * gimple-fold.c (canonicalize_constructor_val): Strip again all no-op + conversions on entry but add them back on exit if needed. + 2012-11-05 Andreas Schwab * final.c (final_scan_insn) [HAVE_cc0]: Handle all comparison diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 66d076664cc..969cfeb5829 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -139,7 +139,8 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) tree canonicalize_constructor_val (tree cval, tree from_decl) { - STRIP_USELESS_TYPE_CONVERSION (cval); + tree orig_cval = cval; + STRIP_NOPS (cval); if (TREE_CODE (cval) == POINTER_PLUS_EXPR && TREE_CODE (TREE_OPERAND (cval, 1)) == INTEGER_CST) { @@ -182,8 +183,12 @@ canonicalize_constructor_val (tree cval, tree from_decl) /* Fixup types in global initializers. */ if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0))) cval = build_fold_addr_expr (TREE_OPERAND (cval, 0)); + + if (!useless_type_conversion_p (TREE_TYPE (orig_cval), TREE_TYPE (cval))) + cval = fold_convert (TREE_TYPE (orig_cval), cval); + return cval; } - return cval; + return orig_cval; } /* If SYM is a constant variable with known value, return the value. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af92ce4c7f5..e870aa5bb9f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-11-05 Eric Botcazou + + * g++.dg/torture/20121105-1.C: New test. + 2012-11-05 Andreas Schwab * gcc.dg/torture/fp-compare.c: New testcase. diff --git a/gcc/testsuite/g++.dg/torture/20121105-1.C b/gcc/testsuite/g++.dg/torture/20121105-1.C new file mode 100644 index 00000000000..03323421a5e --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/20121105-1.C @@ -0,0 +1,42 @@ +// PR tree-optimization/54986 +// Reported by Remi Vanicat +// Reduced testcase by Markus Trippelsdorf + +struct A; +struct B +{ + int *_ptr; + bool operator==(B *p1) + { + return p1->_ptr; + } +}; +struct C { + A* ref_SYMBptr(); +}; +struct A +{ + B sommet; +}; +typedef C *gen_op_context; +struct D +{ + D(gen_op_context) {} +}; + +D c(0); +const long d = (long)&c; +B *const e = (B *)&d; + +static bool +fn1(C& p1) +{ + return p1.ref_SYMBptr()->sommet == e; +} + +void +fn2() +{ + C b; + fn1(b); +}