From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zack Weinberg To: craig@jcb-sc.com Cc: egcs@egcs.cygnus.com Subject: Re: Uninitialized variable warnings Date: Mon, 15 Mar 1999 20:03:00 -0000 Message-id: <199903160403.XAA28775@blastula.phys.columbia.edu> In-reply-to: Your message of "15 Mar 1999 21:12:32 GMT." < 19990315211232.23607.qmail@deer > References: <19990315211232.23607.qmail@deer> X-SW-Source: 1999-03/msg00529.html >>>>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 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zack Weinberg To: craig@jcb-sc.com Cc: egcs@egcs.cygnus.com Subject: Re: Uninitialized variable warnings Date: Wed, 31 Mar 1999 23:46:00 -0000 Message-ID: <199903160403.XAA28775@blastula.phys.columbia.edu> References: <19990315211232.23607.qmail@deer> X-SW-Source: 1999-03n/msg00534.html Message-ID: <19990331234600.y-s40Jv5vpDhHmzFB5t9GVOCh-4v9EKtM5zNmQ6Afr0@z> >>>>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