I have a program with an addition function for int8_t that is intended to check for overflow. Regardless of whether the test works, I get different results from the program if I compile it with -O1 vs compiling with -O2. It appears that GCC is performing optimisations it shouldn't across the process boundaries that lead to the wrong behaviour. In particular, GCC is effectively saying that it has the value 128 in an int8_t. This is not specifically a printf problem, as the overflow is not set with -O1, and is set with -O2. Running with -O1, the program runs all the tests successfully. With -O2, there is a failure, where GCC says it is adding the int8_t values 0 and 128 during the loop. Compare that with the earlier lines where it correctly says it is trying to add 0 and -128 in the standalone tests. Here's the complete code of the reduced test-case (the .i file is no different apart from the included headers, and the includes are all standard C headers):
#include <stddef.h> #include <stdbool.h> #include <stdint.h> #include <limits.h> #include <stdio.h> int g_overflow; static inline int8_t add_int8_t (int8_t, int8_t, const char *); static inline int8_t add_int8_t (int8_t a, int8_t b, const char *pos) { printf("int8_t : adding %d and %d\n", (int)a, (int)b); if (((b<1)&&(-128-b<=a)) || ((b>=1)&&(127-b>=a))) { return a + b; } else { g_overflow = 1; return 0; } } int main(int argc, char** argv) { g_overflow = 0; const int8_t result = add_int8_t(-128,0,""); printf("-128 + 0, result: %d, overflow: %d", (int)result, g_overflow); g_overflow = 0; const int8_t resultB = add_int8_t(0,-128,""); printf("-128 + 0, result: %d, overflow: %d", (int)resultB, g_overflow); // Test commutativity: int done_x_once = 0; for (int8_t x = 0; !(x == 0 && done_x_once == 1);x++) { done_x_once = 1; int done_y_once = 0; for (int8_t y = 0; !(y == 0 && done_y_once == 1);y++) { done_y_once = 1; g_overflow = 0; const int8_t r0 = add_int8_t(x,y,""); const int overflow_earlier = g_overflow; g_overflow = 0; const int8_t r1 = add_int8_t(y,x,""); const int overflow_later = g_overflow; if ((overflow_later == 1 && overflow_earlier == 1) || (overflow_earlier == 0 && overflow_later == 0 && r0 == r1)) { //Passed } else { printf("Comm failed, non-commutative with %d, %d (overflow: %d, %d) (res: %d, %d)\n", (int)x, (int)y, overflow_earlier, overflow_later, r0, r1); goto failed_comm; } } } failed_comm:; return 0; } Here is my gcc -v output (I'm using the latest standard GCC on Ubuntu): Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu11' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu Thread model: posix gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu11) Command-line to get correct behaviour (pasting the above code into gccbug.c) is: gcc -std=gnu99 gccbug.c -O1 Command-line to trigger the bug is: gcc -std=gnu99 gccbug.c -O2 There is no compiler output, and adding -Wall still gives no compiler output. -- Summary: Optimisation with inline function causes invalid behaviour Product: gcc Version: 4.3.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: gcc at twistedsquare dot com GCC build triplet: i486-linux-gnu GCC host triplet: i486-linux-gnu GCC target triplet: i486-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38929