Bug 49754 - Wuninitialized does not work with structs/unions/arrays
Summary: Wuninitialized does not work with structs/unions/arrays
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.5.1
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL: https://bugzilla.novell.com/show_bug....
Keywords:
: 42561 (view as bug list)
Depends on:
Blocks: Wuninitialized 89976
  Show dependency treegraph
 
Reported: 2011-07-15 06:16 UTC by Christopher Yeleighton
Modified: 2020-06-23 21:03 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-10-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christopher Yeleighton 2011-07-15 06:16:27 UTC
The compiler gcc currently warns about uninitialized scalar variables but not
about compound variables.

== Steps to Reproduce ==
  1. 
{ cat>foo.c<<'/* EOF */' && gcc -Wall -pedantic-errors foo.c; }
struct i { int x; };
struct i foo () { struct i x; return x; }
int bar () { int y; return +y; }
/* EOF */

== Actual Results ==  
foo.c: In function ‘bar’:
foo.c:3:21: warning: ‘y’ is used uninitialized in this function


== Expected Results ==  
foo.c: In function ‘foo’:
foo.c:2:?: warning: ‘x’ is used uninitialized in this function
foo.c: In function ‘bar’:
foo.c:3:21: warning: ‘y’ is used uninitialized in this function
Comment 1 Jonathan Wakely 2011-07-15 08:36:30 UTC
(In reply to comment #0)
> == Expected Results ==  
> foo.c: In function ‘foo’:
> foo.c:2:?: warning: ‘x’ is used uninitialized in this function

It should really warn if 'x.i' is used uninitialized, not 'x'
Comment 2 Christopher Yeleighton 2011-07-15 09:35:42 UTC
(In reply to comment #1)
> (In reply to comment #0)
> > == Expected Results ==  
> > foo.c: In function ‘foo’:
> > foo.c:2:?: warning: ‘x’ is used uninitialized in this function
> 
> It should really warn if 'x.i' is used uninitialized, not 'x'

Since (x) is uninitialized, so is (x.i).  It is impossible to recognize the problem when (x.i) is eventually accessed by a client of foo:

{
struct i x = foo (); 
printf ("%i", +x.i);
}
Comment 3 Jonathan Wakely 2011-07-15 09:56:49 UTC
(In reply to comment #2)
> Since (x) is uninitialized, so is (x.i).

But what if x.i gets initialized, is x still uninitialized?


struct X { int i; };
struct Y { int i; int j; };

int main()
{
  X x;
  x.i = 0;   // is 'x' initialized now?
  Y y;
  y.i = 0;   // is 'y' initialized now?
  y.j = 0;   // is 'y' initialized now?
}


It would be possible to track the initialization of each subobject *and* the aggregate, but it would be more overhead
Comment 4 Jonathan Wakely 2011-07-15 10:16:12 UTC
Just to be clear - I completely agree that uninit'd warnings need improving, I'm not objecting to that.  But in my experience (mostly C++) I'd prefer to have it tracked at the more fine-grained level of sub-objects.
Comment 5 Christopher Yeleighton 2011-07-15 11:00:28 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > Since (x) is uninitialized, so is (x.i).
> 
> But what if x.i gets initialized, is x still uninitialized?

If (x.i) denotes an object type and the initial value means "x is empty" then x is initialized.

> 
> struct X { int i; };
> struct Y { int i; int j; };
> 
> int main()
> {
>   X x;
>   x.i = 0;   // is 'x' initialized now?
>   Y y;
>   y.i = 0;   // is 'y' initialized now?
>   y.j = 0;   // is 'y' initialized now?
> }
> 
> 
> It would be possible to track the initialization of each subobject *and* the
> aggregate, but it would be more overhead

I have already bumped into this using arrays, where GCC does emit a warning although it should not:

int a [02]; 
for (a [0] = 0;;) if (a [0]) printf ("%d", +a [1]); else a [0] = a [1] = 01;
Comment 6 Manuel López-Ibáñez 2012-10-04 08:23:24 UTC
This is a problem of representation. Struct/unions/arrays are represented as memory operations, and Wuninitialized does not (generally) work on them. It may warn in some corner cases if the accesses can be converted into scalar variables, but in general it doesn't work.

I am not even sure if the current middle-end representation can tell whether the memory is uninitialized and never initialized up to the point of use. That would be the first thing to implement.
Comment 7 Manuel López-Ibáñez 2018-09-16 17:03:45 UTC
*** Bug 42561 has been marked as a duplicate of this bug. ***
Comment 8 Martin Sebor 2020-06-23 21:03:58 UTC
GCC 11 (and prior) diagnose both functions in comment #0, I suspect as a result of r156156:

pr49754.c: In function ‘foo’:
pr49754.c:2:38: warning: ‘x’ is used uninitialized [-Wuninitialized]
    2 | struct i foo () { struct i x; return x; }
      |                                      ^
pr49754.c:2:28: note: ‘x’ declared here
    2 | struct i foo () { struct i x; return x; }
      |                            ^
pr49754.c: In function ‘bar’:
pr49754.c:3:28: warning: ‘y’ is used uninitialized [-Wuninitialized]
    3 | int bar () { int y; return +y; }
      |                            ^~

Returning larger aggregates started to be diagnosed in r245840.  Passing structs to other functions by value still isn't diagnosed.  It used to be, but it stopped  sometime between r143699 and r143725.

See pr95848 that tracks the problem with pass-by-value.