Bug 78391 - g++ (any version) at O0 (for O1, O2, O3 is ok) doesn't warn when class members are used uninitialized.
Summary: g++ (any version) at O0 (for O1, O2, O3 is ok) doesn't warn when class member...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: 12.4
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2016-11-17 09:27 UTC by Luca Stoppa
Modified: 2023-05-08 12:21 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 10.2.0, 11.0, 7.3.0, 8.3.0, 9.2.0
Last reconfirmed: 2021-03-31 00:00:00


Attachments
Minimal testcase that shows the (possible) problem. (76 bytes, text/plain)
2016-11-17 09:27 UTC, Luca Stoppa
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Luca Stoppa 2016-11-17 09:27:31 UTC
Created attachment 40063 [details]
Minimal testcase that shows the (possible) problem.

It seems like g++ (any version) doesn't warn when class members are uninitialized when no optimization is enabled (and at -O0). For -O1, -O2, -O3 we correctly get a warning (On the contrary, clang, any version, reports a warning at any optimization level).

struct data { int x=w; int w=10; };

int main() {
    data d;
    return d.x;
}

g++ ub.cpp -Wall -Wextra -std=gnu++1z -O0 
=> no warning

g++ ub.cpp -Wall -Wextra -std=gnu++1z -O1
=> 
ub.cpp: In function 'int main()':
ub.cpp:4:10: warning: 'd.data::w' is used uninitialized in this function [-Wuninitialized]
     data d;

for -O2, -O3 we get exactly the same warning.
Comment 1 Richard Biener 2016-11-17 09:35:54 UTC
-Wuninitialized requires optimization to handle this case.
Comment 2 Luca Stoppa 2016-11-17 10:03:27 UTC
(In reply to Richard Biener from comment #1)
> -Wuninitialized requires optimization to handle this case.

I see thanks. Considering that I found this bug in our unit tests, I'll simply add -O1 in order to avoid in the future this issue in our code.
Comment 3 Andrew Pinski 2016-11-18 04:22:08 UTC
There might be a dup of this bug already.  Linking against the meta-bug about uninit warnings.
Comment 4 Martin Sebor 2021-04-01 00:38:16 UTC
Reconfirmed with GCC 11.

GCC does issue -Wuninitialized without optimization on an equivalent test case with an explicit ctor.  The difference between the two ctors is that B's has a clobber:

$ cat pr78391.C && PRED_DUMP=euninit gcc -S -Wall pr78391.C
struct A { int x = w; int w = 10; };

int f ()
{
  A a;
  return a.x;
}

struct B { int x, w; B (): x(w), w (10) { } };

int g ()
{
  B b;
  return b.x;
}

void A::A (struct A * const this)
{
  int _1;

  <bb 2> :
  # VUSE <.MEM_2(D)>           <<< no clobber
  _1 = this_3(D)->w;           <<< -Wuninitialized
  # .MEM_4 = VDEF <.MEM_2(D)>
  this_3(D)->x = _1;
  # .MEM_5 = VDEF <.MEM_4>
  this_3(D)->w = 10;
  # VUSE <.MEM_5>
  return;

}


int f ()
{
  struct A a;
  int D.2439;
  int _3;

  <bb 2> :
  # .MEM_2 = VDEF <.MEM_1(D)>
  A::A (&a);
  # VUSE <.MEM_2>
  _3 = a.x;
  # .MEM_4 = VDEF <.MEM_2>
  a ={v} {CLOBBER};

  <bb 3> :
<L1>:
  # VUSE <.MEM_4>
  return _3;

}


void B::B (struct B * const this)
{
  int _1;

  <bb 2> :
  # .MEM_4 = VDEF <.MEM_2(D)>
  *this_3(D) ={v} {CLOBBER};   <<< clobber here
  # VUSE <.MEM_4>
  _1 = this_3(D)->w;           <<< -Wuninitialized
  # .MEM_5 = VDEF <.MEM_4>
  this_3(D)->x = _1;
  # .MEM_6 = VDEF <.MEM_5>
  this_3(D)->w = 10;
  # VUSE <.MEM_6>
  return;

}


pr78391.C: In constructor ‘B::B()’:
pr78391.C:9:30: warning: ‘*this.B::w’ is used uninitialized [-Wuninitialized]
    9 | struct B { int x, w; B (): x(w), w (10) { } };
      |                              ^
int g ()
{
  struct B b;
  int D.2442;
  int _3;

  <bb 2> :
  # .MEM_2 = VDEF <.MEM_1(D)>
  B::B (&b);
  # VUSE <.MEM_2>
  _3 = b.x;
  # .MEM_4 = VDEF <.MEM_2>
  b ={v} {CLOBBER};

  <bb 3> :
<L1>:
  # VUSE <.MEM_4>
  return _3;

}
Comment 5 Martin Sebor 2021-04-01 00:46:14 UTC
So the missing warning seems like it might be due to a bug in the C++ front end.
Comment 6 Martin Sebor 2021-04-02 16:49:00 UTC
In bug 19808 comment #38 Jason explains why the CLOBBER isn't present in the constructor, so that's not a bug.  In light of that, I'm not sure the request can be implemented without introducing what are strictly speaking false positives like those Clang suffers from.  In the test case below, the global a is implicitly zeroed out first and then its members are explicitly assigned, so there is no uninitialized read.

At the same time, I suspect the result of this initialization is probably not going to be what the author intended, and so warning on it regardless might actually be useful (admittedly, issuing -Wuninitialized in this case would be a bit misleading).  So with that, -Wuninitialized or -Wmaybe-uninitialized in the middle end could be probably enhanced to detect this pattern of intialization dependencies.  Marek submitted a C++ patch for a subset of pr19808 last November but I'm not sure it handled this case.  The patch was also not approved as Jason's preference was to detect these things in the middle end.  So let me reassign this back to the middle end and try to remember to get to it for GCC 12.

$ cat t.C && clang -S t.C
struct A { int x = w; int w = 10; };

A a;
t.C:1:20: warning: field 'w' is uninitialized when used here [-Wuninitialized]
struct A { int x = w; int w = 10; };
                   ^
t.C:3:3: note: in implicit default constructor for 'A' first required here
A a;
  ^
t.C:1:8: note: during field initialization in the implicit default constructor
struct A { int x = w; int w = 10; };
       ^
1 warning generated.
Comment 8 Eric Gallager 2021-11-19 16:20:37 UTC
(In reply to Martin Sebor from comment #7)
> Patch for pr19808:
> https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559162.html

That's fixed now.
Comment 9 Martin Sebor 2022-01-26 17:32:40 UTC
This has been improved in GCC 12 but GCC still doesn't diagnose the original test case at -O0.  It seems that it should be able to, either in the C++ front end or even in the middle end.  I'm not working on this anymore.
Comment 10 Jakub Jelinek 2022-05-06 08:29:56 UTC
GCC 12.1 is being released, retargeting bugs to GCC 12.2.
Comment 11 Richard Biener 2022-08-19 08:23:23 UTC
GCC 12.2 is being released, retargeting bugs to GCC 12.3.
Comment 12 Richard Biener 2023-05-08 12:21:23 UTC
GCC 12.3 is being released, retargeting bugs to GCC 12.4.