The following code seems to be correctly executed when compiled with GCC 4.4.7 and LLVM 6.1. Yet i don't think it correctly compiles with gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4).
The following is what I have reduced the problem to:
#include <stdio.h>
#include <stdlib.h>
#define GENERAL 1
#define BRACKETS 2
#define QUOTES 3
//This method contains the issue.
void foo(char *qb, char* into) {
//The starting state is important for the bug.
int state = QUOTES;
int save_state = BRACKETS;
//This here needs to reference qb in some way, previously I
//had this as just qb however I will set it to qb[0]. Note that this
//is a contrived example, I already know that setting it to one
//makes this pass which makes me suspect this is a compiler
//issue.
while (qb[0]) {
printf("State is %d\n", state);
switch (state) {
case BRACKETS:
printf("Yay this was correctly executed\n");
exit(0);
break;
case GENERAL:
printf("Oh no how did you get here?\n");
printf("State is %d\n", state);
exit(1);
break;
case QUOTES:
state = save_state;
printf("State went to %d btw BRACKETS is %d\n", state, BRACKETS);
save_state = GENERAL; //Remove this line and it will work even
when optimised.
printf("After save state, state went to %d btw BRACKETS is
%d\n", state, BRACKETS);
break;
default: ;
}
printf("State %d btw GENERAL %d\n", state, GENERAL);
}
printf("If you see this then something is really wrong.\n");
exit(4);
}
int main() {
//These don't seem to matter don't concern yourself with them.
char *b = "123";
char out[4];
foo(b, out);
return 1;
}
If I compile this with: gcc -O0 -g -Wall -Werror sillyswitch.c -o sillyswitch
It will print
Yay this was correctly executed
which is what I expect it to print
However if I compile this with: gcc -O -g -Wall -Werror sillyswitch.c -o sillyswitch
It will print
Oh no how did you get here?
Which is not what I expect to see.
I don't under why it does not work as expected when optimisation is turned on. Is the code wrong in that the branch of the switch statement taken on the second loop is arbitrary? As it is C did I shoot myself in the foot somehow?
Failed full output:
State is 3
State went to 2 btw BRACKETS is 2
After save state, state went to 2 btw BRACKETS is 2
State 2 btw GENERAL 1
State is 2
Oh no how did you get here?
State is 1
Success full output:
State is 3
State went to 2 btw BRACKETS is 2
After save state, state went to 2 btw BRACKETS is 2
State 2 btw GENERAL 1
State is 2
Yay this was correctly executed