Bug 96629 - spurious maybe uninitialized variable warning with difficult control-flow analysis
Summary: spurious maybe uninitialized variable warning with difficult control-flow ana...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 10.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2020-08-16 06:10 UTC by Yichao Yu
Modified: 2022-11-20 04:50 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-08-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yichao Yu 2020-08-16 06:10:25 UTC
Reduced test code:

```
int mem(char *data);
int cond(void);
void f(char *data, unsigned idx, unsigned inc)
{
    char *d2;
    int c = cond();
    if (idx >= 2) {
        if (c)
            d2 = data;
        mem(data);
    }
    else if (inc > 3) {
        if (c)
            d2 = data;
        mem(data);
    }
    else {
        if (c) {
            d2 = data;
        }
    }
    if (*data) {
    }
    else if (c) {
        mem(d2);
    }
}
```

Compiling with `gcc -Wall -Wextra -O{1,2,s,3,fast}` warns about

```
a.c: In function 'f':
a.c:27:9: warning: 'd2' may be used uninitialized in this function [-Wmaybe-uninitialized]
   27 |         mem(d2);
      |         ^~~~~~~
```

However, it should be clear that `d2` is always assigned when `c` is true. In fact, it seems that GCC could figure this out in some cases. Changes that can surpress the warning includes,

1. Remove any of the `mem(data)` calls.
2. Remove any one of the `if`s (leaving only the if or else branch unconditionally)
3. Change first condition to be on inc instead.
4. Removing the last `*data` branch.

Version tested:
AArch64: 10.2.0
ARM: 9.1.0
x86_64: 10.1.0
mingw64: 10.2.0
Comment 1 Richard Biener 2020-08-25 10:20:19 UTC
the control-flow analysis of the uninit warning isn't powerful enough to capture this.
Comment 2 Manuel López-Ibáñez 2020-09-03 18:13:41 UTC
Yes, the pass seems to give up:

[CHECK]: Found unguarded use: d2_29 = PHI <d2_4(19), data_13(D)(22)>
[WORKLIST]: Update worklist with phi: d2_29 = PHI <d2_4(19), data_13(D)(22)>
[CHECK]: examining phi: d2_29 = PHI <d2_4(19), data_13(D)(22)>
[CHECK]: Found unguarded use: mem (d2_29); [tail call]
Comment 3 Yichao Yu 2020-09-03 18:21:03 UTC
Just curious, is it some particular structure that is upsetting it or did it simply hit some depth limit.
Comment 4 Jeffrey A. Law 2022-11-20 04:50:14 UTC
It's worth noting that at -O2, -O3 and -Ofast the warning does not trigger.  I haven't dug deeply as this is fairly common.  At higher optimization levels the various optimizers try harder to find and eliminate redundancies.