Hi! As the testcase shows, the folding which previously has been done only in tree-ssa-forwprop.c breaks some cases with explicit casts in -Wconversion, so this patch limits that folding to GIMPLE only. Unfortunately that breaks a few cases in builtin-isinf_sign-1.c test at -O0, but IMNSHO expecting all the folding at -O0 is wrong, outside of constexpr and initializers we shouldn't guarantee any folding.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-04-05 Jakub Jelinek <ja...@redhat.com> PR c++/70336 * match.pd (nested int casts): Limit to GIMPLE. * c-c++-common/pr70336.c: New test. * gcc.dg/torture/builtin-isinf_sign-1.c (foo): Guard tests no longer optimized away at -O0 with #ifndef __OPTIMIZE__. --- gcc/match.pd.jj 2016-03-23 19:25:56.000000000 +0100 +++ gcc/match.pd 2016-04-04 12:39:32.535498926 +0200 @@ -1554,7 +1554,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* A truncation to an unsigned type (a zero-extension) should be canonicalized as bitwise and of a mask. */ - (if (final_int && inter_int && inside_int + (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion. */ + && final_int && inter_int && inside_int && final_prec == inside_prec && final_prec > inter_prec && inter_unsignedp) --- gcc/testsuite/c-c++-common/pr70336.c.jj 2016-04-04 12:42:48.056806268 +0200 +++ gcc/testsuite/c-c++-common/pr70336.c 2016-04-04 12:44:19.343549096 +0200 @@ -0,0 +1,37 @@ +/* PR c++/70336 */ +/* { dg-do compile } */ +/* { dg-options "-Wconversion" } */ + +void +f1 (unsigned char * x, int y, int z) +{ + x[z / 8] |= (unsigned char) (0x80 >> y); /* { dg-bogus "may alter its value" } */ +} + +unsigned char +f2 (unsigned char x, int y) +{ + x = x | (unsigned char) (0x80 >> y); /* { dg-bogus "may alter its value" } */ + return x; +} + +unsigned char +f3 (unsigned char x, int y) +{ + x = x | (unsigned char) (y & 255); /* { dg-bogus "may alter its value" } */ + return x; +} + +unsigned char +f4 (unsigned char x, unsigned char y) +{ + x = x | (unsigned char) (y & 255); /* { dg-bogus "may alter its value" } */ + return x; +} + +unsigned char +f5 (unsigned char x, int y) +{ + x = (unsigned char) (y & 255); /* { dg-bogus "may alter its value" } */ + return x; +} --- gcc/testsuite/gcc.dg/torture/builtin-isinf_sign-1.c.jj 2008-09-05 12:54:28.000000000 +0200 +++ gcc/testsuite/gcc.dg/torture/builtin-isinf_sign-1.c 2016-04-05 16:13:40.649320108 +0200 @@ -24,6 +24,7 @@ foo (float f, double d, long double ld) != (__builtin_isinf(ld) ? (__builtin_signbitl(ld) ? -1 : 1) : 0)) link_error (__LINE__); +#ifdef __OPTIMIZE__ /* In boolean contexts, GCC will fold the inner conditional expression to 1. So isinf_sign folds to plain isinf. */ @@ -33,6 +34,7 @@ foo (float f, double d, long double ld) link_error (__LINE__); if ((_Bool)__builtin_isinf_sign(ld) != (__builtin_isinf(ld) != 0)) link_error (__LINE__); +#endif if ((__builtin_isinf_sign(f) != 0) != (__builtin_isinf(f) != 0)) link_error (__LINE__); Jakub