Testcase based on an xbubble build error on Debian: $ cat test.c struct _Bubble { int color; }; typedef struct _Bubble * Bubble; typedef enum { EAST=0, NORTH_EAST, NORTH_WEST, WEST, SOUTH_WEST, SOUTH_EAST } Quadrant; struct _CellArray { Bubble cell[(8 * 12)]; int first_row; }; typedef struct _CellArray * CellArray; void cell_array_lower( CellArray ca ) { int i; for ( i = ( ca->first_row*8 ); i < ( ca->first_row*8 ) + 8; i++ ) ca->cell[i] = ((void *)0); } $ gcc-6 -O2 -Wall -Werror -c test.c $ gcc-6 -O3 -Wall -Werror -c test.c $ gcc -O2 -Wall -Werror -c test.c $ gcc -O3 -Wall -Werror -c test.c test.c: In function ‘cell_array_lower’: test.c:25:17: error: assuming signed overflow does not occur when assuming that (X + c) >= X is always true [-Werror=strict-overflow] ca->cell[i] = ((void *)0); ~~~~~~~~~~~~^~~~~~~~~~~~~ cc1: all warnings being treated as errors $ It works when replacing the "+ 8" in the loop condition with a variable whose value is not known at compile time.
This is the loop distribution generated size argument to memcpy: <bb 2> [15.00%]: _1 = ca_7(D)->first_row; i_8 = _1 * 8; _13 = _1 + 1; _14 = _13 * 8; _17 = (unsigned int) _14; _2 = (unsigned int) i_8; _3 = _17 - _2; _5 = _3 + 4294967295; _4 = (sizetype) _5; _12 = _4 + 1; _11 = _12 * 8; _18 = i_8 < _14 ? _11 : 8; _19 = _1 * 8; _20 = (sizetype) _19; _21 = _20 * 8; _22 = ca_7(D) + _21; __builtin_memset (_22, 0, _18); which later during forwprop which sees <bb 2> [15.00%]: _1 = ca_7(D)->first_row; i_8 = _1 * 8; _14 = i_8 + 8; _18 = i_8 < _14 ? 64 : 8; _19 = _14 - 8; _20 = (sizetype) _19; _21 = _20 * 8; _22 = ca_7(D) + _21; __builtin_memset (_22, 0, _18); is optimized i_8 < i_8 + 8 -> 1 to <bb 2> [15.00%]: _1 = ca_7(D)->first_row; i_8 = _1 * 8; _14 = i_8 + 8; _18 = 64; _19 = i_8; _20 = (sizetype) i_8; _21 = _20 * 8; _22 = ca_7(D) + _21; __builtin_memset (_22, 0, _18); this warning is somewhat fragile in that it triggers quite randomly and also on compiler-generated intermediate code in case it gets a location. Also warns on trunk. I suppose we should look into niter analysis why it generates that conditional and/or make sure niter generated GENERIC ends up with TREE_NO_WARNING set and/or no location.
I'm a bit unsure how you want to proceed here Richi. Marc's changes to move key folding patterns from fold-const.c into match.pd means the x + 1 > x -> 1 simplification happens earlier/more often. So the problematical sequence gets wiped out by VRP2. That's probably a good thing. However, that bit of match.pd does not warn when it makes that assumption. One could argue it should. Of course if it warns, then we end up in situations like this BZ where the warning spit out by GCC bears no resemblance to the actual source code because of ldist or other significant code transformations. So I could make an argument to drop the 8 from the regression marker. I could make an argument we should open a new BZ for the missed warning and/or a BZ for getting the code coming out of ldist sane. Thoughts?
The warning no longer occurs on trunk, re-confirmed on the branch. I think there's two sides generally 1) the strict-overflow warnings out of middle-end folding code are just too fragile, we're getting rid of them 2) the question is what location stmts should have for code generated by GCC (like that stmts to compute the memset size). We currently assign a location near the emission place but one could argue it should be UNKNOWN_LOCATION (or ARTIFICIAL_LOCATION if there would be sth like this). We'd then simply avoid emitting warnings with no good location, aka treating the stmts as artificial (compiler-generated). Index: gcc/tree-loop-distribution.c =================================================================== --- gcc/tree-loop-distribution.c (revision 255402) +++ gcc/tree-loop-distribution.c (working copy) @@ -813,7 +813,7 @@ generate_memset_builtin (struct loop *lo /* The new statements will be placed before LOOP. */ gsi = gsi_last_bb (loop_preheader_edge (loop)->src); - nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter, + nb_bytes = build_size_arg_loc (UNKNOWN_LOCATION, partition->main_dr, partition->niter, partition->plus_one); nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE, false, GSI_CONTINUE_LINKING); changes the warning to > ./cc1 -quiet t.c -O3 -Wall -Wstrict-overflow t.c: In function ‘cell_array_lower’: cc1: warning: assuming signed overflow does not occur when assuming that (X + c) >= X is always true [-Wstrict-overflow] which shows we also need sth to prune such useless warnings: Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 255402) +++ gcc/fold-const.c (working copy) @@ -265,7 +265,8 @@ fold_undefer_overflow_warnings (bool iss locus = input_location; else locus = gimple_location (stmt); - warning_at (locus, OPT_Wstrict_overflow, "%s", warnmsg); + if (locus != UNKNOWN_LOCATION) + warning_at (locus, OPT_Wstrict_overflow, "%s", warnmsg); } /* Stop deferring overflow warnings, ignoring any deferred another side-effect might be that we avoid some jumping in gdb if we don't assign line info to this kind of stmts.
Richi. I do worry about cases where we exploit strict-overflow semantics. It'd be nice to be able to warn about them, but I certainly agree that stability is a problem. With instability, messaging to and expectations of the user community become serious concerns. I won't object to moving them out of the middle end. WRT locations/diagnostics for things like ldist where GCC conjures up code that has little resemblance to what the user wrote. It's a real issue once we issue the warning -- the user has no clue what it meant. On the other hand those warnings (particularly those that result from ldist) are highlighting real issues. Bogus user code, poor optimization, even under-specified language from ISO. Examples of all can be found in BZ.
On Tue, 5 Dec 2017, law at redhat dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81876 > > --- Comment #4 from Jeffrey A. Law <law at redhat dot com> --- > Richi. > > I do worry about cases where we exploit strict-overflow semantics. It'd be > nice to be able to warn about them, but I certainly agree that stability is a > problem. The main issue with this warning is that it warns about perfectly valid code... IMHO warning about simplifying a_1 + 1 > a_1 is not about strict-overflow but is in the "comparison is always true" class. But suggesting that there's a overflow issue in the code is misleading. > On the other hand those warnings (particularly those that result from ldist) > are highlighting real issues. Bogus user code, poor optimization, even > under-specified language from ISO. Examples of all can be found in BZ. Well... see above. Optimization is never perfect and passes doing code-generation do rely on followup passes to optimize things.
(In reply to Jeffrey A. Law from comment #4) > WRT locations/diagnostics for things like ldist where GCC conjures up code > that has little resemblance to what the user wrote. It's a real issue once > we issue the warning -- the user has no clue what it meant. > > On the other hand those warnings (particularly those that result from ldist) > are highlighting real issues. Bogus user code, poor optimization, even > under-specified language from ISO. Examples of all can be found in BZ. If in doubt, don't issue any warning to the user. As far as I am aware, the testcase in this bug does not warrant any warning in that line - even "comparison is always true" would be wrong. If a warning option sometimes generates bogus warnings for issues not present in the code, the only reasonable option for a user would be to always disable this warning.
GCC 7.3 is being released, adjusting target milestone.
Doesn't occur with GCC 8.
*** Bug 79877 has been marked as a duplicate of this bug. ***