On Fri, 17 Feb 2017, Marek Polacek wrote: > For "(int) -x", which is a NOP_EXPR, negate_expr_p returns true, which means > that fold_negate_expr cannot return NULL_TREE. But that's what happens here, > leading to a crash in fold_build2. negate_expr_p has (as well as negate_expr) > STRIP_SIGN_NOPS, so the "(int) -x" becomes "-x", but fold_negate_expr doesn't > have any STRIP_SIGN_NOPS. Richi suggested to add a wrapper for > fold_negate_expr > that strips/restores such NOP_EXPRs, much like negate_expr, which is what this > patch does. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? And 6 after a while?
Ok. Thanks, Richard. > 2017-02-16 Marek Polacek <pola...@redhat.com> > > PR middle-end/79536 > * fold-const.c (fold_negate_expr_1): Renamed from fold_negate_expr. > (fold_negate_expr): New wrapper. > > * gcc.dg/torture/pr79536.c: New test. > > diff --git gcc/fold-const.c gcc/fold-const.c > index a8bb8af..ad4770b 100644 > --- gcc/fold-const.c > +++ gcc/fold-const.c > @@ -139,6 +139,7 @@ static tree fold_relational_const (enum tree_code, tree, > tree, tree); > static tree fold_convert_const (enum tree_code, tree, tree); > static tree fold_view_convert_expr (tree, tree); > static bool vec_cst_ctor_to_array (tree, tree *); > +static tree fold_negate_expr (location_t, tree); > > > /* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION. > @@ -522,7 +523,7 @@ negate_expr_p (tree t) > returned. */ > > static tree > -fold_negate_expr (location_t loc, tree t) > +fold_negate_expr_1 (location_t loc, tree t) > { > tree type = TREE_TYPE (t); > tree tem; > @@ -533,7 +534,7 @@ fold_negate_expr (location_t loc, tree t) > case BIT_NOT_EXPR: > if (INTEGRAL_TYPE_P (type)) > return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0), > - build_one_cst (type)); > + build_one_cst (type)); > break; > > case INTEGER_CST: > @@ -581,14 +582,14 @@ fold_negate_expr (location_t loc, tree t) > case COMPLEX_EXPR: > if (negate_expr_p (t)) > return fold_build2_loc (loc, COMPLEX_EXPR, type, > - fold_negate_expr (loc, TREE_OPERAND (t, 0)), > - fold_negate_expr (loc, TREE_OPERAND (t, 1))); > + fold_negate_expr (loc, TREE_OPERAND (t, 0)), > + fold_negate_expr (loc, TREE_OPERAND (t, 1))); > break; > > case CONJ_EXPR: > if (negate_expr_p (t)) > return fold_build1_loc (loc, CONJ_EXPR, type, > - fold_negate_expr (loc, TREE_OPERAND (t, 0))); > + fold_negate_expr (loc, TREE_OPERAND (t, 0))); > break; > > case NEGATE_EXPR: > @@ -605,7 +606,7 @@ fold_negate_expr (location_t loc, tree t) > { > tem = negate_expr (TREE_OPERAND (t, 1)); > return fold_build2_loc (loc, MINUS_EXPR, type, > - tem, TREE_OPERAND (t, 0)); > + tem, TREE_OPERAND (t, 0)); > } > > /* -(A + B) -> (-A) - B. */ > @@ -613,7 +614,7 @@ fold_negate_expr (location_t loc, tree t) > { > tem = negate_expr (TREE_OPERAND (t, 0)); > return fold_build2_loc (loc, MINUS_EXPR, type, > - tem, TREE_OPERAND (t, 1)); > + tem, TREE_OPERAND (t, 1)); > } > } > break; > @@ -623,7 +624,7 @@ fold_negate_expr (location_t loc, tree t) > if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) > && !HONOR_SIGNED_ZEROS (element_mode (type))) > return fold_build2_loc (loc, MINUS_EXPR, type, > - TREE_OPERAND (t, 1), TREE_OPERAND (t, 0)); > + TREE_OPERAND (t, 1), TREE_OPERAND (t, 0)); > break; > > case MULT_EXPR: > @@ -638,11 +639,11 @@ fold_negate_expr (location_t loc, tree t) > tem = TREE_OPERAND (t, 1); > if (negate_expr_p (tem)) > return fold_build2_loc (loc, TREE_CODE (t), type, > - TREE_OPERAND (t, 0), negate_expr (tem)); > + TREE_OPERAND (t, 0), negate_expr (tem)); > tem = TREE_OPERAND (t, 0); > if (negate_expr_p (tem)) > return fold_build2_loc (loc, TREE_CODE (t), type, > - negate_expr (tem), TREE_OPERAND (t, 1)); > + negate_expr (tem), TREE_OPERAND (t, 1)); > } > break; > > @@ -715,6 +716,19 @@ fold_negate_expr (location_t loc, tree t) > return NULL_TREE; > } > > +/* A wrapper for fold_negate_expr_1. */ > + > +static tree > +fold_negate_expr (location_t loc, tree t) > +{ > + tree type = TREE_TYPE (t); > + STRIP_SIGN_NOPS (t); > + tree tem = fold_negate_expr_1 (loc, t); > + if (tem == NULL_TREE) > + return NULL_TREE; > + return fold_convert_loc (loc, type, tem); > +} > + > /* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T can not be > negated in a simpler way. Also allow for T to be NULL_TREE, in which case > return NULL_TREE. */ > diff --git gcc/testsuite/gcc.dg/torture/pr79536.c > gcc/testsuite/gcc.dg/torture/pr79536.c > index e69de29..6f05ca7 100644 > --- gcc/testsuite/gcc.dg/torture/pr79536.c > +++ gcc/testsuite/gcc.dg/torture/pr79536.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile } */ > + > +typedef int A; > +int > +fn1 (A x, A y) > +{ > + if ((x + (x - y) * 1i) != -(-x + (y - x) * 1i)) > + return 1; > + return 0; > +} > > Marek > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)