Bug 82601 - missing uninitialized warning for INTENT(OUT) argument with -O0 / -Og
Summary: missing uninitialized warning for INTENT(OUT) argument with -O0 / -Og
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: 12.4
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2017-10-18 08:13 UTC by janus
Modified: 2023-05-08 12:21 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 10.2.0, 11.0, 8.3.0, 9.3.0
Last reconfirmed: 2021-04-02 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description janus 2017-10-18 08:13:13 UTC
Consider this simple Fortran test case:


program uninit

   integer :: p,q
   p = -1
   call sub(p, q)
   if (p<q) print *,"..."

contains

   subroutine sub(i, o)
      integer, intent(in) :: i
      integer, intent(out) :: o
      if (i<0) then
         print *, "..."
      else
         o = 1
      end if
   end subroutine

end


With -Wall and -O1 (or higher), all recent gfortran versions print:

    if (p<q) print *,"..."
 
Warning: ‘q’ is used uninitialized in this function [-Wuninitialized]


However, with -O0 or -Og, no warning is issued.

It should be possible to detect that 'o' may be uninitialized by looking only at the subroutine itself (without any information about the caller).
Comment 1 Richard Biener 2017-10-18 09:04:57 UTC
The warning is issued because we inline sub.

As we do not know whether 'o' is used we don't issue a warning in sub() that
o is not initialized (does intent(out) mean it comes in uninitialized?).
Just looking at the program sub has intent(out) q and thus we can reasonably
expect it to be initialized.

So - is 'o' uninitialized in

subroutine test(o)
 integer, intent(out) :: o
 print *, o
end subroutine

?  It doesn't seem so (we don't warn but I also think we have no way to
annotate sth as uninitalized that is passed by reference).
Comment 2 janus 2017-10-19 13:51:59 UTC
(In reply to Richard Biener from comment #1)
> (does intent(out) mean it comes in uninitialized?)

Yes. To quote the Fortran 2008 standard (from section 5.3.10):

"The INTENT (OUT) attribute for a nonpointer dummy argument specifies that the dummy argument becomes undefined on invocation of the procedure, except for any subcomponents that are default-initialized (4.5.4.6)."


> So - is 'o' uninitialized in
> 
> subroutine test(o)
>  integer, intent(out) :: o
>  print *, o
> end subroutine
> 
> ?

Absolutely (see above). Even if the actual argument has been initialized before invocation of the subroutine, the Fortran standard requires the compiler to treat 'o' as being uninitialized on entering the subroutine.


> (we don't warn but I also think we have no way to
> annotate sth as uninitalized that is passed by reference).

:(
Comment 3 janus 2017-10-19 14:00:34 UTC
Here is a variant of the example in comment 0, where the subroutine has been substituted by a function:


program uninit

   integer :: p,q
   p = -1
   q = f(p)
   if (p<q) print *,"..."

contains

   function f(i) result(o)
      integer, intent(in) :: i
      integer :: o
      if (i<0) then
         print *, "..."
      else
         o = 1
      end if
   end function

end


This neither gives a warning (with -Wall) nor a runtime error (with -fcheck=all), but the function result (and thereby q) is clearly uninitialized.

If I remove the conditional initialization of 'o' completely, I get:

Warning: Return value ‘o’ of function ‘f’ declared at (1) not set [-Wreturn-type]
Comment 4 Dominique d'Humieres 2017-12-30 15:40:25 UTC
Confirmed from 4.8 up to trunk (8.0).
Comment 5 Martin Sebor 2021-04-02 22:02:47 UTC
Pr31279 asks for a warning for a warning for call-by-reference arguments with known intent(in).  This is the converse, but as I mentioned in pr31279 comment #7 the middle end infrastructure to issue these warnings is in place.  The Fortran front end needs to make use of it.

That being said, detecting read accesses to write-only arguments within the annotated function itself isn't implemented yet (only passing uninitialized arguments to read-only arguments is).  So I suggest tracking the Fortran changes in pr31279 and the missing middle-end support here.

$ cat z.c && gcc -S -Wall z.c
__attribute__ ((access (read_only, 1)))
void f1 (int *);

void f2 (void)
{
  int i;
  f1 (&i);         // -Wuninitialized (good)
}

__attribute__ ((access (write_only, 1)))
int g1 (int *p)
{
  return *p;       // missing warning
}

z.c: In function ‘f2’:
z.c:7:3: warning: ‘i’ is used uninitialized [-Wuninitialized]
    7 |   f1 (&i);         // -Wuninitialized (good)
      |   ^~~~~~~
z.c:2:6: note: in a call to ‘f1’ declared with attribute ‘access (read_only, 1)’ here
    2 | void f1 (int *);
      |      ^~
z.c:6:7: note: ‘i’ declared here
    6 |   int i;
      |       ^
Comment 6 Martin Sebor 2022-03-17 20:16:16 UTC
I'm no longer working on this.
Comment 7 Jakub Jelinek 2022-05-06 08:30:01 UTC
GCC 12.1 is being released, retargeting bugs to GCC 12.2.
Comment 8 Richard Biener 2022-08-19 08:23:27 UTC
GCC 12.2 is being released, retargeting bugs to GCC 12.3.
Comment 9 Richard Biener 2023-05-08 12:21:27 UTC
GCC 12.3 is being released, retargeting bugs to GCC 12.4.