https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79536
--- Comment #7 from rguenther at suse dot de <rguenther at suse dot de> --- On Thu, 16 Feb 2017, mpolacek at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79536 > > --- Comment #6 from Marek Polacek <mpolacek at gcc dot gnu.org> --- > Yes, but see my Comment 3 regarding STRIP_SIGN_NOPS. > > Also the typedef is necessary, otherwise there are no NOP_EXPRs (huh). Yeah, but the issue is really fold_negate_expr: case NOP_EXPR: /* Convert -((double)float) into (double)(-float). */ if (TREE_CODE (type) == REAL_TYPE) { tem = strip_float_extensions (t); if (tem != t && negate_expr_p (tem)) return fold_convert_loc (loc, type, negate_expr (tem)); } break; vs. negate_expr_p: STRIP_SIGN_NOPS (t); the type stripping has to be consistent. Thus the fix is to add the same STRIP_SIGN_NOPS to fold_negate_expr (negate_expr does it as well!) or to remove it everywhere and handle the cases allowed in case NOP_EXPR: by recursing. Note it needs to fold back the result to the correct type (like negate_expr does). Most easily by making fold_negate_expr a wrapper around fold_negate_expr_1 and stripping/restoring the nop in the wrapper. Not sure if we had it at some point. My oldest source is GCC 4.3 and it behaves the same way.