Bug 107838 - spurious "may be used uninitialized" warning on variable initialized at the first iteration of a loop
Summary: spurious "may be used uninitialized" warning on variable initialized at the f...
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 13.0
: P3 normal
Target Milestone: ---
Assignee: Richard Biener
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2022-11-23 16:25 UTC by Vincent Lefèvre
Modified: 2023-01-12 07:33 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-11-23 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vincent Lefèvre 2022-11-23 16:25:10 UTC
Consider

int f(void);
void g(int *t)
{
  int i, v;
  for (i = 0; i < 9; i++)
    {
      if (i == 0)
        v = f();
      if (v + t[i])
        f();
    }
}

$ gcc-test -O -Wmaybe-uninitialized -c tst3.c
tst3.c: In function ‘g’:
tst3.c:9:13: warning: ‘v’ may be used uninitialized [-Wmaybe-uninitialized]
    9 |       if (v + t[i])
      |           ~~^~~~~~
tst3.c:4:10: note: ‘v’ was declared here
    4 |   int i, v;
      |          ^

The variable v is initialized at the first iteration (i == 0). Therefore the warning is incorrect.

This occurs with GCC 4.8, 6.5.0, 8.4.0, 9.5.0, 12.2.0, and 13.0.0 20220906 (experimental) from the master branch. But there are no warnings with GCC 4.9, 5.5.0, 10.4.0 and 11.3.0.

Note to myself (to check once this bug is fixed): this testcase is derived from tmd/binary32/hrcases.c (warning on variable b).
Comment 1 Richard Biener 2022-11-23 20:59:37 UTC
I will have a look
Comment 2 Richard Biener 2022-11-24 10:20:08 UTC
I think there's a duplicate bug, we fail to pick up the controlling condition
because IVOPTs replaced the exit test but we still have

  i_19 = (int) ivtmp.4_6;
  if (i_19 == 0)

...

  <bb 7> [local count: 966367643]:
  ivtmp.4_21 = ivtmp.4_6 + 1;
  if (ivtmp.4_21 != 9)

thus with -fno-ivopts the predication code works fine.  It doesn't try
hard enough to consider "derived" conditions like the above.
Comment 3 Guilherme Janczak 2023-01-11 21:03:40 UTC
I just ran into the same bug with the following code:

/* rand32: return 32 bits of randomness */
static
unsigned long rand32(void)
{
	int rand(void);
	unsigned long rval;

	/*
	 * There is modulo bias in this example if RAND_MAX isn't a power of 2
	 * minus 1, but that is irrelevant for the bug report.
	 *
	 * C only guarantees RAND_MAX is at least 32767, that is, 15 bits.
	 */
	rval = rand() & 0x7FFF;
	rval <<= 15;
	rval |= rand() & 0x7FFF;
	rval <<= 2;
	rval |= rand() & 0x03;
	return rval;

}

/* rand_hex: fill a buffer with random hex digits */
void rand_hex(unsigned char *buf, int len)
{
	const char *hex = "0123456789ABCDEF";
	int i;
	unsigned long r;

	for (i = 0; i < len; i++) {
		/* If we don't have any random bits in r, get some more. */
		if (i % 8 == 0)
			r = rand32();

		/* Use 4 bits from the 32-bit integer at a time. */
		buf[i] = hex[r & 0x0F];
		r >>= 4;
	}
}

$ gcc -O -c -Wmaybe-uninitialized test.c
test.c: In function 'rand_hex':
test.c:37:19: warning: 'r' may be used uninitialized in this function [-Wmaybe-uninitialized]
   37 |                 r >>= 4;
      |                 ~~^~~~~


Notice how the 1st usage of r doesn't cause the warning, but the 2nd one does.
I haven't tested GCC 13.0.0, I get this with the GCC 12.2.1 from Alpine Linux and 11.2.0 from OpenBSD, here's their respective `gcc -v` outputs:
gcc version 12.2.1 20220924 (Alpine 12.2.1_git20220924-r4)
gcc version 11.2.0 (GCC)
Comment 4 Richard Biener 2023-01-12 07:33:27 UTC
comment#3 is a slightly different issue in that we do not have the guarding
condition obviously true here, instead what we'd need to prove is that
r_8 is always initialized because the first loop iteration initializes it.

Maybe it's somehow possible to code that into the uninit analysis machinery,
I'd have to think about this.