The following fixes pre/post-inc/dec gimplification of promoted integer types. There is the issue with the way TYPE_OVERFLOW_UNDEFINED is related to TYPE_OVERFLOW_WRAPS and the (non-)semantics of -fno-strict-overflow.
In this case, with -On -fno-strict-overflow for a variable of type short we have !TYPE_OVERFLOW_WRAPS _and_ !TYPE_OVERFLOW_UNDEFINED (so we're in an "undefined" area). Which means that !TYPE_OVERFLOW_UNDEFINED doesn't imply that overflow wraps. Thus the gimplification has to play on the safe side and always use an unsigned type unless the user specifies -fwrapv (the flag with a proper semantic meaning). That is, it seems to be the case that what predicate to use (TYPE_OVERFLOW_WRAPS or TYPE_OVERFLOW_UNDEFINED, independent on whether you invert it), depends on the use-case in a very awkward (and error-prone) way. Bootstrap and regtest pending on x86_64-unknown-linux-gnu, ok if that succeeds (I expect to have to adjust some testcases)? Thanks, Richard. 2014-05-14 Richard Biener <rguent...@suse.de> c-family/ * c-gimplify.c (c_gimplify_expr): Gimplify self-modify expressions using unsigned arithmetic if overflow does not wrap instead of if overflow is undefined. * c-c++-common/torture/pr61184.c: New testcase. Index: gcc/c-family/c-gimplify.c =================================================================== *** gcc/c-family/c-gimplify.c (revision 210354) --- gcc/c-family/c-gimplify.c (working copy) *************** c_gimplify_expr (tree *expr_p, gimple_se *** 199,207 **** tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type)) { ! if (TYPE_OVERFLOW_UNDEFINED (type) ! || ((flag_sanitize & SANITIZE_SI_OVERFLOW) ! && !TYPE_OVERFLOW_WRAPS (type))) type = unsigned_type_for (type); return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type); } --- 199,205 ---- tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type)) { ! if (!TYPE_OVERFLOW_WRAPS (type)) type = unsigned_type_for (type); return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type); } Index: gcc/testsuite/c-c++-common/torture/pr61184.c =================================================================== *** gcc/testsuite/c-c++-common/torture/pr61184.c (revision 0) --- gcc/testsuite/c-c++-common/torture/pr61184.c (working copy) *************** *** 0 **** --- 1,18 ---- + /* { dg-do run } */ + /* { dg-additional-options "-fno-strict-overflow" } */ + + short a; + + void + foo (void) + { + for (a = 0; a >= 0; a++) + ; + } + + int + main () + { + foo (); + return 0; + }