https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118702

            Bug ID: 118702
           Summary: -fanalyzer misses
                    -Wanalyzer-use-of-uninitialized-value unless
                    -fno-analyzer-state-merge is supplied
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: dmalcolm at gcc dot gnu.org
  Target Milestone: ---

See https://gcc.gnu.org/pipermail/gcc/2025-January/245436.html

Given

struct T {
   int a;
   int b;
};

extern int bbb (struct T *, int *);
extern int ccc (struct T *, int *);
extern int ddd (struct T *, int);

int
aaa (struct T *t)
{
   int x = 0, y;         /* 'y' is uninitialized */

   if (t->a)             /* if this condition is true */
     goto l;

   x += bbb (t, &y);

  l:
   if (t->b)             /* and this condition is false */
       x += ccc (t, &y);

   x += ddd (t, y);      /* then 'y' is passed to ddd() uninitialized */

   return x;
}

FWIW -fanalyzer doesn't warn:
  https://godbolt.org/z/EvcnMv767

unless I add -fno-analyzer-state-merge :

  https://godbolt.org/z/EvcnMv767

which gives:

<source>: In function 'aaa':
<source>:24:9: warning: use of uninitialized value 'y' [CWE-457]
[-Wanalyzer-use-of-uninitialized-value]
   24 |    x += ddd (t, y);      /* then 'y' is passed to ddd() uninitialized
*/
      |         ^~~~~~~~~~
  'aaa': events 1-7
   13 |    int x = 0, y;         /* 'y' is uninitialized */
      |               ^
      |               |
      |               (1) region created on stack here
      |               (2) capacity: 4 bytes
   14 | 
   15 |    if (t->a)             /* if this condition is true */
      |       ~        
      |       |
      |       (3) following 'true' branch... ─>─┐
      |                                         │
      |                                         │
      |┌────────────────────────────────────────┘
   16 |│     goto l;
      |│     ~~~~      
      |│     |
      |└────>(4) ...to here
......
   21 |    if (t->b)             /* and this condition is false */
      |       ~        
      |       |
      |       (5) following 'false' branch... ─>─┐
      |                                          │
......
      |                                          │
      |┌─────────────────────────────────────────┘
   24 |│   x += ddd (t, y);      /* then 'y' is passed to ddd() uninitialized
*/
      |│        ~~~~~~~~~~
      |│        |
      |└───────>(6) ...to here
      |         (7) ⚠️  use of uninitialized value 'y' here

Arguably the state-merging code could be smarter here; I haven't investigated
the details.

Reply via email to