On Sat, Mar 13, 2010 at 11:07:13AM +0100, Iustin Pop wrote: > So again, sorry if I'm talking stupid things. But here the compiler does > exactly what you required it to do. 0x80000000 as a positive constant doesn't > work already, if you for example try to print it it's stored as a negative
0x80000000 is perfectly valid to put into an int32_t (it is 4 bytes, after all, isn't it?), i'm not sure what you're saying here. interpreted/stored as signed value it has negative value equal to INT_MIN, but interpreted/stored as unsigned it has a positive value. > value (it actually becomes equal to a, -0x80000000), which of course cannot be > negated again because it would overflow. this "equivalence" is a bit sketchy. to get my point, see what happens when you do int32_t a = (int32_t)0x80000000 /* okay */ vs int32_t a = -(int32_t)0x80000000 /* not okay */ > Check this version: > #include <stdint.h> > #include <stdio.h> > > int main(int argc, char *argv[]){ > int32_t a = -0x80000000; /* okay, apparently */ > int32_t b = 0x80000000; > printf("%i\n", b); > printf("%i\n", a==b); > if (argc > 1) b = -b; /* not okay */ > return 0; > } > > The problem occurs at the original assignment to b, not at the negation > of it. you can run it step by step through a debugger (x86/amd64), the OF (overflow) flag will not be set until b is negated. Breakpoint 1, main (argc=2, argv=0x7fffffffe698) at foo.c:4 4 int32_t a = -0x80000000; /* okay, apparently */ (gdb) display $eflags 1: $eflags = [ PF IF ] (gdb) next 5 int32_t b = 0x80000000; 1: $eflags = [ PF IF ] (gdb) 6 printf("%i\n", b); 1: $eflags = [ PF IF ] (gdb) -2147483648 7 printf("%i\n", a==b); 1: $eflags = [ PF IF ] (gdb) 1 8 if (argc > 1) b = -b; /* not okay */ 1: $eflags = [ PF IF ] (gdb) 9 return 0; 1: $eflags = [ CF PF SF IF OF ] > > > #include <stdio.h> > > > #include <limits.h> > > > > > > int main() { > > > long long int j = LLONG_MAX; > > > int check = 0; > > > > > > j -= 10; > > > j += 5; > > > j += 3; > > > j += 2; > > > check = (-j -1 ) == LLONG_MIN; > > > > > > printf("%d\n", check); > > > return 0; > > > } > > > > > > This small test program gives 1 with any combination of the flags below. > > > > why shouldn't it? > > Because I'm wrapping arround while doing arithmetic, and even after that, the > wraparound behaviour results in the original value. No uncertainties. No > aborts > with -ftrapv. i don't see any wraparound there, i see you subtract 10 from the max value, add it back, and then subtract one from the negated value, all of this is within the bounds of LLONG_MIN...LLONG_MAX. then again i haven't had my coffee this morning so maybe i'm missing something :) > > i'm not saying it *isn't* a compiler error, but inserting a few printfs and > > the problem disappearing is also pretty common in other situations of > > "undefined behavior"... > > I disagree here. Undefined behaviour related to integer arithmetic > should only corrupt the values in question, and a printf can't magically > make them correct again. So yes, it might be a compiler bug, but I still > don't think it's related to 64-bit arithmetic, but rather something else > (storage of 64-bits values in registers/memory? optimization of such > values? etc.). undefined behavior means "undefined behavior". a program can crash or print out haikus to the console, no assumptions :) > I'll run a compile with trapv, but a few small tests with the > ZigZagEncode64/ZigZagDecode64 a -ftrapv shows there is no overflow. Expect > results in a few hours… i ran a compile last night with ftrapv along with all those warning flags, and it produced, around 4000(!) lines of warnings and resulted in an abort different from what we see in the buildd log: /bin/bash: line 1: 25502 Aborted $oldpwd/protoc -I. --cpp_out=$oldpwd google/protobuf/unittest.proto google/protobuf/unittest_empty.proto google/protobuf/unittest_import.proto google/protobuf/unittest_mset.proto google/protobuf/unittest_optimize_for.proto google/protobuf/unittest_embed_optimize_for.proto google/protobuf/unittest_custom_options.proto google/protobuf/unittest_lite.proto google/protobuf/unittest_import_lite.proto google/protobuf/unittest_lite_imports_nonlite.proto google/protobuf/unittest_no_generic_services.proto google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto you get that too? it seems that many of the warnings are valid (using signed ints to represent size, etc), but ultimately i'm guessing they're not related to the problem at hand. if you want i can send you the stderr output from the build, might be useful to look for correlations from the aborting codepath. sean --
signature.asc
Description: Digital signature