Bug 22197 - inconsistent uninitialized warning for structs (SRA, DCE)
Summary: inconsistent uninitialized warning for structs (SRA, DCE)
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.0.1
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2005-06-27 13:25 UTC by Michael Matz
Modified: 2009-02-07 16:18 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-02-07 16:18:20


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Matz 2005-06-27 13:25:17 UTC
Compile this code with -O2 -Wall on 4.0.x or mainline: 
------------------------------------- 
struct testme { 
    int testval; 
    int unusedval; 
}; 
extern void forget (struct testme forgotten); 
int main () { 
    struct testme testarray[1]; 
    struct testme testvar; 
    testvar.testval = 0; 
    testarray[0] = testvar; 
    forget (testarray[0]); 
    return 0; 
} 
-------------------------------------- 
 
This will give this warning: 
unused.c:13: warning: ‘testvar.unusedval’ is used uninitialized in this 
function 
 
The problem is the copy of some uninitialized part.  Yes, it does copy 
something uninitialized, but that's okay, as long as it is not really 
accessed.  At the very least it should only be a "may be used uninit" 
warning.  This is only noticed by tree-sra.  With -fno-tree-sra there's 
no warning.  So, in effect, accesses to uninitialized parts for purpose 
of copying should not lead to such warning.
Comment 1 Andrew Pinski 2005-06-27 13:31:37 UTC
but isn't that the same as (except it is an aggregate in the case in comment #1):
void g(int);
void f(void)
{
 int i;
  g(i);
}

because g might not look at the agrument value?
Comment 2 Michael Matz 2005-06-27 13:50:36 UTC
Hmm, sort of.  The call of g(i) also warns with "is used", although I 
think it might deserve only a "may be used".  But anyway I think that 
this nevertheless has different causes.  It's not the call creating 
the problem, but the copy itself.  On could for instance delete the 
call and instead make 'testarray' volatile (so that the copy is not 
optimized away).  This would still warn, IMHO incorrectly. 
 
What's even stranger is, that if I add a call "forget(testvar)" then 
the warning vanishes.  I.e. like so: 
------------------------------------- 
int main() { 
    struct testme volatile testarray[1]; 
    struct testme testvar; 
    testvar.testval = 0; 
    testarray[0] = testvar; 
    forget (testvar); 
    return 0; 
} 
------------------------------------- 
 
So this shows that not the call on a partly initialized struct is the 
problem (because that is still the case with the above), but something 
in SRA dealing with the copy.  If one removes the call to forget above 
the warning will return (note the added volatile) on the copy. 
Comment 3 Andreas Schwab 2005-06-27 13:57:54 UTC
In the case of g(i) you have an initialisation of the parameter variable which 
already constitutes a use of the value. 
Comment 4 Gabriel Dos Reis 2005-11-26 07:44:36 UTC
(In reply to comment #2)
> Hmm, sort of.  The call of g(i) also warns with "is used", although I 
> think it might deserve only a "may be used".  But anyway I think that 
> this nevertheless has different causes.  It's not the call creating 
> the problem, but the copy itself. 

yes, how a is copy not a use?  At the very list, on modern architectures,
it implies memory->register->memory traffic of garbage data.
Comment 5 Manuel López-Ibáñez 2009-02-07 16:18:20 UTC
This is an interaction between SRA deciding to create separate variables for testval and unusedval because of the copy and DCE deciding whether to remove all references to unusedval because of the call.

The copy is an use, but if the result is not used, then DCE removes it and the warning goes away. If you pass something to a function, that is an use. In particular, the BLOCK is not conditional and there is no PHI node: so the uninitialized value "is used". GCC does not warn for forget(testvar) because SRA is not applied there and hence GCC does not know whether elements of testvar are uninitialized.

Ideally, we should warn in all cases or in none. I would rather warn in all cases as we do for simple variables. If testvar is completely uninitialized and passed to a function, we should definitely get a warning.

Anyway, this will be hard to get right because we would need to look within structures. This is more an enhancement request.