Uninitialized variable warnings
Zack Weinberg
zack@rabi.columbia.edu
Wed Mar 31 23:46:00 GMT 1999
>>>>There are a number of other places where gcc has gotten it wrong, and
>>>>a few places where the warning indicates a real bug. There's also one
>>>>worrisome case, where we get it right or not unpredictably:
[...]
>>>Could you be more precise about "unpredictably"?
[...]
>>I mean that given two similar chunks of code one will get a warning
>>and the other won't, and the significant difference may seem to be
>>absolutely irrelevant as far as a human is concerned. A good example
>>is the `plist' variable in objc-act.c:generate_protocol_list. We warn
>>on that. Prune everything else out of the function, and the compiler
>>doesn't warn anymore.
>
>Hmm, so it's possible there's an uninitialized-variable bug in the
>compiler,
Unless we have false _negatives_ in -Wuninitialized, there don't seem
to be any problems with the section of the code (flow - I think) that
generates the warnings.
>but it might just be that the uninitialized-variable analysis
>(including all RTL transforms that precede it) is overly sensitive
>to things that would normally be thought of as irrelevant to the
>issue of whether a particular variable is initialized.
I believe it is CSE which is too sensitive. Here is a real example.
/* x86, 2.93.12 19990314
-O -Wall: warning
-O2 -Wall: warning
-O -Wall -DCASE2: no warning
-O -Wall -DCASE3: warning
-O2 -Wall -DCASE3: no warning */
struct operation {
short op;
char rprio;
#ifndef CASE2
char flags;
#endif
char unsignedp;
long value;
};
extern struct operation cpp_lex (void);
void
cpp_parse_expr (void)
{
int rprio;
struct operation op;
for (;;)
{
op = cpp_lex ();
switch (op.op)
{
case 0:
break;
#ifndef CASE3
case 1:
return;
#endif
case 2:
rprio = 1;
break;
default:
return;
}
if (op.op == 0)
return;
if (rprio != 1)
abort();
}
}
This is too complicated for flow to get the uninit warnings right no
matter which case it is. However, CSE is able to collapse CASE2 down to
for (;;)
{
op = cpp_lex ();
if (op.op != 2)
break;
}
which flow understands. It can do the same with CASE3, but only if -O2.
Now, the only significant differences in -dj dumps for default and
CASE2 are that CASE2 has (subreg:HI (reg:DI N)) in a few places where
default has (reg:HI N), and the single insn that initializes reg N is
different in mode and offset. I don't think there's a good reason for
cse to get this wrong.
zw
More information about the Gcc
mailing list