c++gccswitch-statementcase

a switch jumping in unexpected place


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 #defined. 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 ?


Solution

  • 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.