https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121735
Bug ID: 121735
Summary: Optimization level O2 triggers false warning about
uninitialized usage whereas O1 and O3 are fine.
Product: gcc
Version: 15.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: b.stolk at gmail dot com
Target Milestone: ---
The gcc compiler (O2 only) will warn with "maybe used unitialized" whereas the
code does not use any variable uninitialized.
I have tested this via godbolt, on 15.2.1 and also gcc-trunk, both of which
trigger a false warning about maybe uninitialized variable. Clang does not
warn.
I have created a minimal example code to trigger it.
I have found the following conditions that require it to trigger:
* It needs to be compiled -O2, whereas -O1 and -O3 do not trigger it.
* It needs to use the results in an externally defined function, if I place the
implementation in the file, it no longer triggers. See the two ifdef macros.
Here is the code that triggers it (gcc -c -Wall -Wextra)
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
typedef struct {
float x;
float y;
} pt_t;
typedef struct
{
int len;
pt_t v[8];
} poly_t;
#if 1
// Calling an extern func is a prerequisit for the bug.
extern void print_pt(pt_t p);
#else
// No compiler warning when using this.
void print_pt(pt_t p) { fprintf(stderr, "%f %f\n", p.x, p.y); }
#endif
void process_poly(const poly_t* poly)
{
// Two uninitialized arrays.
float rngx[2];
float rngy[2];
const int len = poly->len;
assert(len > 0);
for (int i=0; i<len; ++i)
{
if (i==0 || poly->v[i].x < rngx[0]) rngx[0] = poly->v[i].x;
if (i==0 || poly->v[i].x > rngx[1]) rngx[1] = poly->v[i].x;
if (i==0 || poly->v[i].y < rngy[0]) rngy[0] = poly->v[i].y;
if (i==0 || poly->v[i].y > rngy[1]) rngy[1] = poly->v[i].y;
}
const pt_t q = { rngx[1] - rngx[0], rngy[1] - rngy[0] };
#if 0
// No compiler warning on uninitialized use of rngx[0] and rngy[0]
fprintf(stderr, "%f %f\n", q.x, q.y);
#else
// compiler warning on unintialized use. (But only when compiling -O2)
print_pt(q);
#endif
}
The incorrect output:
<source>: In function 'process_poly':
<source>:27:15: warning: 'rngx[0]' may be used uninitialized
[-Wmaybe-uninitialized]
27 | float rngx[2];
| ^~~~
<source>:28:15: warning: 'rngy[0]' may be used uninitialized
[-Wmaybe-uninitialized]
28 | float rngy[2];
|
The warning is incorrect, and it is strange that merely changing optimization
level will change what the compiler thinks of the code correctness.
One more remark: dropping down to gcc 14, the warning is stronger:
"uninitialized use" as opposed to the weaker "maybe uninitialized."
Here is a godbolt link that shows the incorrect warning, including for
gcc-trunk:
https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1AB9U8lJL6yAngGVG6AMKpaAVxYM9DgDJ4GmADl3ACNMYhAAVg1SAAdUBUJbBmc3Dz04hJsBX38gllDwqItMKyyGIQImYgIU908uYtKkiqqCHMCQsMjohUrq2rSG3tb2vILugEoLVFdiZHYOAFIAJgBmP2Q3LABqRdXHXvRaPGCAOgQ97EWNAEEV9YZN1x29g4J8VHPL67u1ja3MLt9kwFEpql9Vldbj8CABPGKYLBUba9Yiuay7ADsACEftcAJxUWioJgEbaqPa46EaQnE0nbWGUvGYgAi2xiBGMBCZ1JucIRSJRBDR1mZVJu20lUslfjJ23oDB5EulUo5XO2ADdFhFsQAObUspWLVnslywrlG6F/ZFcH4Aejt20cYmORm2hm2mFUBDCDG2VFcj22eAU7vZxDCmAAjq4Q4R/SRtgQEIDgq5gKcfl6fcQ/RrUHh0OHZcYORA1WSYhMjWsSkp7Y6AqhtmgWDE6GFtgB3KoMPzAbspv2uBJu5MhzO3fOF4uCUsEcucysTLHY/0xYiyqgQQ5hMi7ZbLFYRZHHqjaxyKw%2BkdmnVQ3mKnWHV1Zr42Gq2rBx4c%2B86dFjdUHmUFSzNCA0AYXpTVoc0CAAKmg58xTxGkHW2AAVLtm0DPxEjEPAAC9EXdYhiCYWEFEnO4aSJEkyVzYAKR1I8IkNV8UNpOjtgYxlmINS1qPxCCoNleVGCBNk4hggBaS4FUtfEQTBBcFSBbBtg0F9xQ4/hiG2CBRLwPYWQ0Slg1eeTXwPXFlmxPBq2pfFjW0mkCR/fSjNWNiTKxRxjUcRDZMhLUdSM1i7yBAKGKY7FTNYldou1WKDQkwLLhCuyDTvBS3ORAzjOMjRfP8tLgqSsKWQiy5uKMGLbXimrGKS%2Bq2WM0rsAyirsvYxzco8gqvKK/ySqk2Ego68qsthSLGt45KGp4pK4tarz2s6qacppdz8q8wrisxALRvG9bwum6rFp1FqEqMOaWtSo70sm06ctZFDBOEysl22KNUucxq6pS6T/qWg0bwu7E7qB8HlqxNjtOtDSOLQpsW1QNsOz0ntc37bYBG2HC%2BxsfCiKLEdAVQZFEp1GHDCLaH%2BMcqgNy3Hd3j3G8ViPZYTwPE8LyvZYbyjO8hafLS8VrWh60ctDW3behMd7HG8YJonjhJ/GlFOfTsVcMkBBgwdxLlugcekgB5ZYHME5m5zLKNxc/b9fzuV7bg4KZaE4CJeE8DgtFIVBOAChQZjmQF7h4UgCE0D2pgAaxAVZVlOZO0/TjOADZ9E4SRfdjwPOF4BQQGiGP/Y90g4FgJATYV8hKDrrpkGALgIkFmhaBzEuIGCAvgj8KpYU4KOB%2BYYhYXN4JtEwawR94Vs2EEc2GBggusDTYBnVoKX59ILAWEMYBxAr/e8Ajaw8A1TAS9Pr1Z71hYo9lEoC%2BOYIyIn5wsAL4U8BYPe19iDBHiJgFkmBD5GFdKACuUwiRMGAAoAAangTAXZzYIj9lHfgggRBiHYFIGQghFAqHUKfXQDQDBGBAKYYw5h34l0gFMVAHIki3wtssbY0kADqLpeCoCAZuLAjCIBTEsLPMo9gGBOBcHULw0jRidHCA0DIiQBADHqLEeIaiGCKPyF0IYJQJHND6DUWRgxGjGIEC0aoejxhDFMRovQwxbF%2BA6Po5RYiw7zAkJ7b2%2BdT5Bw4OSXUmdpKZ0kNsYAyBkDbDbqcThEBcCEETJHCYvBy5aAmAnJOKcM75LTtnL2HA86kD9gHIJxdS7R1jlMauiAQAzAIDEPWDdwJo3lmEAIrAFiqFCeEyJ0TYnxOWLwREKShF6BwcIUQ4hCHTJIWoAuFDSBdjIjEeefiOA%2BzKQXIJ5s9YtP1siPpYSIlRJiXEiICT9LOHRgrA8qwuDpJqbAnJydU4FPyTnEpASKlFwsNUzJccfmjN2YEgFwLsmkCAQkOwkggA