I have forked a C++ project and added some cases in a switch. Then it jumps in the middle of the next case. The condition is an int
, the case values are #define
d. As the code is big, I write here something equivalent and simple:
#define AAA 1
#define BBB 2
int X::func(int i) {
bool b = (i == 5);
int v = (b ? 10 : 5);
switch (i) {
case AAA:
if (b && v > 4) {
v = v + 1;
return 0;
}
break;
case BBB:
if (!b || v > 40) {
v = v + 2;
b = false; // direct jump here from the switch for i = AAA
return 0;
}
break;
}
return -1;
}
If I pass AAA to X::func, the code execution jumps directly from the switch
to b = false;
inside the BBB case. In the real code, I have tens of cases, and it happens in the middle. If I comment entierely case BBB
, it jumps at the same place in the comments ! Every case ends with a break;
and has no variable declaration inside. Like here the variables b and v, they are declared before the switch statement.
Part of the cases are in a #ifdef
#endif
block. The additional cases where the problem occur are in this block. The condition is true, so the block is compiled. Anyway, I have tested it after having suppressed these two precompiler statements, and it is the same.
If I add brackets {}
to fully embrasse the cases like here, I still have the same result:
case BBB: {
if (!b || v > 40) {
v = v + 2;
b = false; // direct jump here from the switch for i = AAA
return 0;
}
break;
}
Everything compiles fine and executes the same, either in a debug session or in normal execution. I use gcc 4.5.4 under Eclipse CDT Indigo.
It looks like a compiler bug, but what could be the cause ?
I have build a "cloned" project (project_test) from the original one (project). In the pre-build steps, I have a rsync that copies all source files (the point is to not copy the autotools stuff):
rsync -a --exclude=tests/* --exclude=perf/* --exclude=tools/* --include=*/ --include=*.[ch] --include=*.[ch]pp --exclude=* ${workspace_loc:/project}/ ${workspace_loc:/project_test}/ && cp ${workspace_loc:/project}/tests/one_with_main.cpp ${workspace_loc:/project_test}/tests/
It builds well, and the debugging is as expected.
An alternative could be rsync -a --delete
instead of rsync -a
.