Bug 43361 - missing uninitialized warning without optimization (-O0) (PHI in always_executed basic block)
Summary: missing uninitialized warning without optimization (-O0) (PHI in always_execu...
Status: RESOLVED DUPLICATE of bug 101573
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 58236 58823 69892 84289 92118 (view as bug list)
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2010-03-14 07:54 UTC by Sebastian Mach
Modified: 2022-08-29 13:25 UTC (History)
10 users (show)

See Also:
Host: (see details)
Target: (see details)
Build: (see details)
Known to work:
Known to fail:
Last reconfirmed: 2021-03-29 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sebastian Mach 2010-03-14 07:54:00 UTC
I've searched several of the other Wunitialized reports, but without deeper knowledge, I wasn't able to conclude whether this is a dup.

Note that even if i happens to be zero-initialized, it is only in this strapped-down testcase. In the program I am hacking, I got an out-of-bound of roughly 2^31 over an array of 6 elements, pretty deep in a expression template hierarchy.

================================================================================

//Tested with (-Wall -Wextra):
//  * g++-4.3 (Debian 4.3.4-6) 4.3.4
//  * g++-4.4 (Debian 4.4.2-9) 4.4.3 20100108 (prerelease)
//  * g++ (GCC) 4.5.0 20100306 (experimental)
#include <iostream>
int main () {
        int i;
        int array[10];
        //std::cout << i;               // get warning, okay
        for (; i<10; ++i) {             // no warning
                std::cout << i;         // no warning
                array [i] = i;          // no warning, really hurts
        }
        // sidenote: same results for 
        //   for (int i; i<N; ++i) {...}
}

================================================================================
Full triplets:

Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.4-6' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.3.4 (Debian 4.3.4-6)


Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.2-9' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.3 20100108 (prerelease) (Debian 4.4.2-9)


Using built-in specs.
COLLECT_GCC=/usr/local/gcc-4.5-20100306/bin/g++
COLLECT_LTO_WRAPPER=/usr/local/gcc-4.5-20100306/libexec/gcc/x86_64-unknown-linux-gnu/4.5.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --prefix=/usr/local/gcc-4.5-20100306 --enable-languages=c,c++ --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-checking --disable-nls --disable-multilib --enable-bootstrap --with-gcc --with-gnu-as --with-gnu-ld --with-gomp --with-lto
Thread model: posix
gcc version 4.5.0 20100306 (experimental) (GCC)
Comment 1 Manuel López-Ibáñez 2010-03-14 15:45:50 UTC
In GCC 4.3.x you need optimization enabled for Wuninitialized.

In GCC 4.4.1 and GCC 4.5 (trunk) I get warnings in line 6 with -O1 -O2 and -O3.

We do not get a warning with -O0 because the default definition appears in a PHI node:

<bb 2>:
  [pr43361.C : 6 : 3] goto <bb 4>;

<bb 3>:
  [pr43361.C : 7:19] std::basic_ostream<char>::operator<< ([pr43361.C : 7] &cout, i_1);
  [pr43361.C : 8:18] [pr43361.C : 8] array[i_1] = i_1;
  [pr43361.C : 6:3] i_4 = i_1 + 1;

<bb 4>:
  # i_1 = PHI <i_2(D)(2), [pr43361.C : 6:3] i_4(3)>
  [pr43361.C : 6:3] D.21125_3 = i_1 <= 9;
  [pr43361.C : 6:3] if (D.21125_3 != 0)
    goto <bb 3>;
  else
    goto <bb 5>;

<bb 5>:
  [pr43361.C : 0:0] D.21127_5 = 0;
  return D.21127_5;


This can be seen as a natural limitation of the analysis at -O0 or a problem with the way GCC represents loops:

for (init; test; next) { for-body }; is transformed to:

init:
 init;
 goto eval
body:
  for-body;
  next;
  goto eval;
eval:
 (test) ? goto body : goto finish;
finish:

So, although we know what "test" is evaluated at least once after init, GCC doesn't know that with -O0.

In any case, there is no trivial fix (but there is a workaround: use optimization).
Comment 2 Richard Biener 2010-03-15 11:27:33 UTC
(In reply to comment #1)
> In GCC 4.3.x you need optimization enabled for Wuninitialized.
> 
> In GCC 4.4.1 and GCC 4.5 (trunk) I get warnings in line 6 with -O1 -O2 and -O3.
> 
> We do not get a warning with -O0 because the default definition appears in a
> PHI node:
> 
> <bb 2>:
>   [pr43361.C : 6 : 3] goto <bb 4>;
> 
> <bb 3>:
>   [pr43361.C : 7:19] std::basic_ostream<char>::operator<< ([pr43361.C : 7]
> &cout, i_1);
>   [pr43361.C : 8:18] [pr43361.C : 8] array[i_1] = i_1;
>   [pr43361.C : 6:3] i_4 = i_1 + 1;
> 
> <bb 4>:
>   # i_1 = PHI <i_2(D)(2), [pr43361.C : 6:3] i_4(3)>
>   [pr43361.C : 6:3] D.21125_3 = i_1 <= 9;
>   [pr43361.C : 6:3] if (D.21125_3 != 0)
>     goto <bb 3>;
>   else
>     goto <bb 5>;
> 
> <bb 5>:
>   [pr43361.C : 0:0] D.21127_5 = 0;
>   return D.21127_5;
> 
> 
> This can be seen as a natural limitation of the analysis at -O0 or a problem
> with the way GCC represents loops:
> 
> for (init; test; next) { for-body }; is transformed to:
> 
> init:
>  init;
>  goto eval
> body:
>   for-body;
>   next;
>   goto eval;
> eval:
>  (test) ? goto body : goto finish;
> finish:
> 
> So, although we know what "test" is evaluated at least once after init, GCC
> doesn't know that with -O0.
> 
> In any case, there is no trivial fix (but there is a workaround: use
> optimization).

The trivial fix would be to compute post-dominator info and check if the
edge with the uninitialized use is executed on all paths from function
entry to exit (its source and destination post-dominate the entry bb).

Comment 3 Manuel López-Ibáñez 2010-03-15 13:42:37 UTC
(In reply to comment #2)
> 
> The trivial fix would be to compute post-dominator info and check if the
> edge with the uninitialized use is executed on all paths from function
> entry to exit (its source and destination post-dominate the entry bb).

You want to do that at -O0?
Comment 4 Richard Biener 2010-03-15 14:27:36 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > 
> > The trivial fix would be to compute post-dominator info and check if the
> > edge with the uninitialized use is executed on all paths from function
> > entry to exit (its source and destination post-dominate the entry bb).
> 
> You want to do that at -O0?

Not really.

Comment 5 Paolo Carlini 2011-09-28 22:40:56 UTC
Basing on the discussion, I'm closing this as wontfix.
Comment 6 Manuel López-Ibáñez 2013-10-21 12:08:03 UTC
*** Bug 58823 has been marked as a duplicate of this bug. ***
Comment 7 Manuel López-Ibáñez 2013-10-31 00:50:04 UTC
*** Bug 58236 has been marked as a duplicate of this bug. ***
Comment 8 Manuel López-Ibáñez 2016-02-21 22:15:22 UTC
*** Bug 69892 has been marked as a duplicate of this bug. ***
Comment 9 Manuel López-Ibáñez 2016-02-22 23:13:50 UTC
Jakub sketched a possible way to warn about this at -O0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69723#c7

Thus, let's reopen it.
Comment 10 Manuel López-Ibáñez 2018-02-08 23:09:36 UTC
*** Bug 84289 has been marked as a duplicate of this bug. ***
Comment 11 Eric Gallager 2019-02-10 23:41:20 UTC
(In reply to Manuel López-Ibáñez from comment #9)
> Jakub sketched a possible way to warn about this at -O0:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69723#c7
> 
> Thus, let's reopen it.

cc-ing him (and a few others)
Comment 12 Manuel López-Ibáñez 2019-12-16 20:04:54 UTC
*** Bug 92118 has been marked as a duplicate of this bug. ***
Comment 13 Jason Merrill 2020-01-06 18:31:09 UTC
Not a C++ issue; removing the use of iostreams from the testcase and compiling as C has the same result.
Comment 14 Martin Sebor 2021-03-29 17:19:44 UTC
Reconfirmed with GCC 11 and the C test case below:

void f (int);

int main () {
        int i;
        int array[10];
        for (; i<10; ++i) {             // no warning
                f (i);                  // no warning
                array [i] = i;          // no warning, really hurts
        }
}
Comment 15 Richard Biener 2021-03-30 07:10:41 UTC
(In reply to Martin Sebor from comment #14)
> Reconfirmed with GCC 11 and the C test case below:
> 
> void f (int);
> 
> int main () {
>         int i;
>         int array[10];
>         for (; i<10; ++i) {             // no warning
>                 f (i);                  // no warning
>                 array [i] = i;          // no warning, really hurts
>         }
> }

So what's going "wrong" here is that we figure the BB with the i<10 check
post-dominates the entry block and thus is always executed.  But when
doing warn_uninit on the SSA var we do not consider the value on the
always-executed path from entry (which is uninitialized i_3(D)).

That's for the early pass, the late pass doesn't run at -O0.

Note since we walk BBs in index order which 'i' we warn for is probably
random, I think we'll only warn once since we set TREE_NO_WARNING on the
underlying decl of the SSA name (that's probably misguided - different
SSA defs can have different uninit state).

It might be possible to populate possibly_undefined_names in the BB walk
by visiting PHIs and considering fallthru entries being taken to have this
work out without major restructuring of the pass (a lattice of "undefinedness"
would probably be more to the point).
Comment 16 Richard Biener 2022-08-29 13:25:34 UTC
Note GCC 12 now diagnoses this at -O0, reporting the first use:

> ../../obj-gcc12-g/gcc/cc1 -quiet t.c -Wall
t.c: In function 'main':
t.c:5:13: warning: variable 'array' set but not used [-Wunused-but-set-variable]
    5 |         int array[10];
      |             ^~~~~
t.c:6:17: warning: 'i' is used uninitialized [-Wuninitialized]
    6 |         for (; i<10; ++i) {             // no warning
      |                ~^~~
t.c:4:13: note: 'i' was declared here
    4 |         int i;
      |             ^

PR101573 is a "duplicate" we have a testcase for now.

*** This bug has been marked as a duplicate of bug 101573 ***