With GCC 13.2, the output of the following code depends on the optimization level:
#include <ctype.h>
#include <stdio.h>
char *SkipAName(char *s) {
if (('A' <= *s && *s <= 'Z') || ('a' <= *s && *s <= 'z') || *s == '_' ||
*s == '$') {
if (*s == '$') {
s++;
}
while (isalnum(*s)) {
s++;
}
if (*s == '_') {
s++;
}
}
return s;
}
int TestName(char *name) {
while (*name) {
name++;
}
return 0;
}
int StrICmp(char *s1, char *s2) {
while (*s1 && tolower(*s1) == tolower(*s2)) {
s1++;
s2++;
}
return tolower(*s1) - tolower(*s2);
}
int DoTable(char *s) {
char *name, c;
do {
name = s;
s = SkipAName(s);
c = *s;
*s = 0;
TestName(name);
*s = c;
if (*s == '(') {
break;
}
if (*s != ',') {
printf("Error 1\n");
return 1;
}
*s = 0;
if (StrICmp(name, "sparse") == 0) {
} else {
printf("Error 2\n");
return 1;
}
*s++ = ',';
while (*s == ',') {
s++;
}
} while (*s);
printf("OK\n");
return 0;
}
int main() {
char buf[] = "sparse,C(1)";
DoTable(buf);
return 0;
}
$ gcc-13 -O0 test.c && ./a.out
OK
$ gcc-13 -O1 test.c && ./a.out
OK
$ gcc-13 -O2 test.c && ./a.out
Error 2
$ gcc-13 -O3 test.c && ./a.out
Error 2
The code comes from this project and I have tried to make a minimal reproducible example; that is why this code may look awkward. See also this issue.
I am wondering if this is a bug in GCC 13 or if I have hit some undefined behaviour. With Compiler Explorer, it looks like somehow *s = 0
at line 52 is optimized away. The code works fine with GCC 12.3.
*s = 0;
line is important and has a clearly visible effect. Thus, it should not be optimized out. I can only guess that the compiler is getting 'confused' by the earlier occurrence of the same C code. – Christologys = SkipAName(s);
(which, in your reduced code, have no nett effect) seems to fix the compiler's output. – ChristologyTestName
isn't really doing anything. But on my system using -O2, the output change if I comment out the call ofTestName
– Pomatumwhile (*s1 && tolower(*s1) == tolower(*s2)) { ...
should be OK for null-terminated stringss1
ands2
. For example,s1 = "abc"
ands2 = "a"
lead to the return value'b' - 0
. – Coextensivetolower(0)
which is0
itself. As such, the==
will return 0, exiting the loop. – Cater*s = 0
if it can conclude that this memory location will never be used anyway. Which the compiler may be able to predict by inliningStrICmp
or similar optimization. I can't be bothered to reverse-engineer all of these optimizations... That being said, gcc 13 is a complete bug fest and very far from a stable release. It shouldn't be used. – Klaraklarikamov BYTE PTR [rbp+0], 0
which wasn't there in 13.2. gcc 13.2 has taken "the weekly gcc bug" to "the daily gcc bug". I remember a time when we only had "the yearly gcc bug"... Everyone should seriously consider backing down to gcc 7 or so which is afaik the last stable version with (C11) standard compliance. – Klaraklarika