Consider the following testcase: int foo1 (void); int foo2 (int); #ifdef D #define N #else #define N ! #endif int bar (void) { int i; auto void cf (int *t) { foo2 (i); } int t __attribute__ ((cleanup (cf))); t = 0; if (foo1 ()) i = foo1 (); i = N foo1 () || i; foo2 (i); return 0; } With a GCC snapshot built a few hours ago from the master branch on x86_64: cventin% gcc --version gcc (GCC) 11.0.1 20210406 (experimental) cventin% gcc -Werror=maybe-uninitialized -O2 -c file.c cventin% gcc -Werror=maybe-uninitialized -O2 -c file.c -DD cventin% gcc -Werror=maybe-uninitialized -O2 -c file.c -fsanitize=undefined cventin% gcc -Werror=maybe-uninitialized -O2 -c file.c -fsanitize=undefined -DD file.c: In function ‘bar’: file.c:21:17: error: ‘FRAME.1.i’ may be used uninitialized [-Werror=maybe-uninitialized] 21 | i = N foo1 () || i; | ~~~~~~~~^~~~ file.c:10:5: note: ‘FRAME.1’ declared here 10 | int bar (void) | ^~~ cc1: some warnings being treated as errors Except in the last case, the warning is missing, though -fsanitize=undefined should have no influence, and whether one does "! foo1 ()" or "foo1 ()" should have no effects either.
Most likely just a dup of bug 83382.
Unless you consider that bug 83382 is actually 2 bugs, this is not a dup. Bug 83382 is about a false positive -Werror=uninitialized error. Do you mean that it also has a missing -Werror=maybe-uninitialized error like here?
Note that with gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, I get the same behavior. But with gcc-9 (Debian 9.3.0-22) 9.3.0, the warning is missing in the 4 cases.
Confirmed. The warning sees the IL below. It's not the same as pr83382 because there's no call to a UBSAN function. The warning here is due to a direct use of a GCC-internal variable (introduced in tree-nested.c). The variable has the DECL_ARTIFICIAL bit set, so maybe also disabling the warning for variables with that bit might make sense. OTOH, its seems like the use of an unintialized variable shouldn't be emitted at all so that might be something to look into first. int bar () { struct FRAME.bar FRAME.1; int _1; int _2; int prephitmp_3; void * _7; int _11; int pretmp_19; int _21; _Bool _22; int _23; <bb 2> [local count: 1073741824]: # .MEM_6 = VDEF <.MEM_5(D)> _7 = __builtin_dwarf_cfa (0); # .MEM_8 = VDEF <.MEM_6> FRAME.1.FRAME_BASE.PARENT = _7; # .MEM_9 = VDEF <.MEM_8> _1 = foo1 (); if (_1 != 0) goto <bb 4>; [33.00%] else goto <bb 3>; [67.00%] <bb 3> [local count: 719407024]: # VUSE <.MEM_9> pretmp_19 = FRAME.1.i; <<< -Wmaybe-uninitialized goto <bb 5>; [100.00%] <bb 4> [local count: 354334800]: # .MEM_10 = VDEF <.MEM_9> _11 = foo1 (); <bb 5> [local count: 1073741824]: # .MEM_4 = PHI <.MEM_9(3), .MEM_10(4)> # prephitmp_3 = PHI <pretmp_19(3), _11(4)> # .MEM_13 = VDEF <.MEM_4> _2 = foo1 (); _21 = _2 | prephitmp_3; _22 = _21 != 0; _23 = (int) _22; # .MEM_15 = VDEF <.MEM_13> FRAME.1.i = _23; # .MEM_16 = VDEF <.MEM_15> foo2 (_23); # .MEM_17 = VDEF <.MEM_16> .UBSAN_NULL (&FRAME.1, 3B, 8); # .MEM_18 = VDEF <.MEM_17> foo2 (_23); # VUSE <.MEM_18> return 0; }
(In reply to Martin Sebor from comment #4) > Confirmed. The warning sees the IL below. It's not the same as pr83382 > because there's no call to a UBSAN function. The warning here is due to a > direct use of a GCC-internal variable (introduced in tree-nested.c). The > variable has the DECL_ARTIFICIAL bit set, so maybe also disabling the > warning for variables with that bit might make sense. Sure not, the 'FRAME' variable is artificial but its members refer to the parent frame user variables which we do want to warn on. IIRC Eric had some patches to dissect 'FRAME' again after inlining to help optimization and diagnostics.
I misread the report: it's actually about a false negative in all the cases where the warning isn't issued and not about it being issued with -fsanitize=undefined in the one case where it is. Mentioning the name of an artificial variable is certainly confusing, but I agree that warnings shouldn't be suppressed for it when it's created as a substitute for a real variable. That said, as the simpler test case case in pr99945 shows, warnings for the FRAME variable were apparently already (perhaps inadvertently) suppressed in r230968.
This has nothing to do with cleanup functions but just nested functions vs SRA. Take: ``` int foo1 (void); int foo2 (int); #ifdef D #define N #else #define N ! #endif int bar (void) { int i; auto void cf (int *t) { foo2 (i); } int t; t = 0; if (foo1 ()) i = foo1 (); i = N foo1 () || i; foo2 (i); cf(&t); return 0; } ``` Which is the same as the original one without the cleanup attribute (basically added the call to cf). Using `-O2 -Wall -DD -fno-tree-sra` causes the following warning the be done: ``` <source>: In function 'bar': <source>:22:17: warning: 'FRAME.1.i' may be used uninitialized [-Wmaybe-uninitialized] 22 | i = N foo1 () || i; | ~~~~~~~~^~~~ <source>:11:5: note: 'FRAME.1' declared here 11 | int bar (void) | ^~~ ``` Without `-fno-tree-sra`, there is no warning because SRA produces: ``` # SR.4_14 = PHI <SR.4_12(D)(5), _9(3)> _2 = foo1 (); _17 = _2 | SR.4_14; ``` which should 100% warn but since SR.4 is artifical does not.
Note basically -fsanitize=undefined in this case stops SRA from happening ...
duplicate. *** This bug has been marked as a duplicate of bug 99959 ***