Bug 56748

Summary: Bogus uninitialized warning with nested if condition
Product: gcc Reporter: Rich Townsend <townsend>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: burnus, jeffreyalaw, manu
Priority: P3 Keywords: diagnostic
Version: 4.8.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:
Bug Depends on:    
Bug Blocks: 24639    
Attachments: Sample code producing bogus warning

Description Rich Townsend 2013-03-26 20:26:34 UTC
Created attachment 29736 [details]
Sample code producing bogus warning

In the attached code, compilation with the following args:

gfortran -O2 -fcheck=all -Wall -c test_uninit.f90

...produces the following warning:

test_uninit.f90: In function ‘mysub’:
test_uninit.f90:13:0: warning: ‘b.0’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      print *, b
 ^

The warning goes away if any of the following modifications are made:

*) any of the compilation flags is omitted
*) the stop statement in the code is commented out
*) the variable 'b' is made non-optional (and the PRESENT check is removed)
*) the variable 'b' is made a scalar

gfortran -v:
Using built-in specs.
COLLECT_GCC=/Applications/madsdk/bin/gfortran.exec
COLLECT_LTO_WRAPPER=/Applications/madsdk/libexec/gcc/x86_64-apple-darwin11.4.2/4.8.0/lto-wrapper
Target: x86_64-apple-darwin11.4.2
Configured with: ./configure CC='gcc -D_FORTIFY_SOURCE=0' --build=x86_64-apple-darwin11.4.2 --prefix=/Applications/madsdk --with-gmp=/Applications/madsdk --with-mpfr=/Applications/madsdk --with-mpc=/Applications/madsdk --enable-languages=c,c++,fortran --disable-multilib
Thread model: posix
gcc version 4.8.0 20130314 (experimental) (GCC)
Comment 1 Tobias Burnus 2013-03-27 08:26:31 UTC
First remark: Bogus uninitialized warnings can not always be prevented. - It is a extremely complex problem, where a few false warnings (and many missed warnings) are unavoidable. Still, one should do better.



If one looks at the dump (-fdump-tree-original, i.e. a C-like output of the internal representation), one sees:


mysub (struct array1_integer(kind=4) & restrict a,
       struct array1_integer(kind=4) * b)
{
...

  if (b != 0B && (integer(kind=4)[0:] * restrict) b->data != 0B)
        b.0 = (integer(kind=4)[0:D.1925] * restrict) b->data;
...
  if (b != 0B && (integer(kind=4)[0:] * restrict) b->data != 0B)
...
              if (b != 0B && (integer(kind=4)[0:] * restrict) b->data != 0B)
                {
                  // Here are some run-time checks, enabled by -fcheck=all
                }
...
          parm.10.data = (void *) &(*b.0)[0];
          _gfortran_transfer_array_write (&dt_parm.9, &parm.10, 4, 0);



As all "if" conditions are the same, b.0 is never uninitialized. However, nesting the same "b != NULL" seems to confuse the uninitialized diagnostic.
Comment 2 Manuel López-Ibáñez 2014-09-11 14:14:51 UTC
There is a uninit dump file that explains what the uninit pass is doing. It would be helpful to see if the condition is in fact too complex or it has been transformed by some optimization pass into something that cannot be handled.
Comment 3 Jeffrey A. Law 2017-03-31 21:34:45 UTC
Not sure when this was fixed, but it works fine on the trunk.  VRP1/DOM2 are able to thread the conditional branches (which removes unexecutable paths) with the net result is all the uninitialized uses of b.0 are ultimately removed.