Bug 49754

Summary: Wuninitialized does not work with structs/unions/arrays
Product: gcc Reporter: Christopher Yeleighton <giecrilj>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: enhancement CC: dimhen, manu, matt, msebor
Priority: P3    
Version: 4.5.1   
Target Milestone: ---   
URL: https://bugzilla.novell.com/show_bug.cgi?id=705160#c1
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95848
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2012-10-04 00:00:00
Bug Depends on:    
Bug Blocks: 24639, 89976    

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.