Hi,

this is a regression present on the 4.7 branch and caused by my fix for 
another regression: http://gcc.gnu.org/ml/gcc-patches/2012-07/msg00825.html

It turns out that canonicalize_constructor_val has side effects: on the 4.7 
branch, it calls add_referenced_var on the base variable of an address (it 
does something similar on mainline) and not calling it for the testcase leads 
to a segfault later because the var_ann of a global variable doesn't exist.

So the STRIP_NOPS is needed for the pattern matching code to work.  That's why 
the attached patch adds it back but makes it so that an appropriate cast is 
added back at the end if necessary.

Bootstrapped/regtested on x86_64-suse-linux, OK for mainline and 4.7 branch?


2012-11-05  Eric Botcazou  <ebotca...@adacore.com>

        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  Eric Botcazou  <ebotca...@adacore.com>

        * g++.dg/torture/20121005-1.C: New test.


-- 
Eric Botcazou
Index: gimple-fold.c
===================================================================
--- gimple-fold.c	(revision 193090)
+++ gimple-fold.c	(working copy)
@@ -139,7 +139,8 @@ can_refer_decl_in_current_unit_p (tree d
 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,
       /* 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.
/* PR tree-optimization/54986 */
/* Reported by Remi Vanicat <vani...@debian.org> */
/* Reduced testcase by Markus Trippelsdorf <mar...@trippelsdorf.de> */

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);
}

Reply via email to