1

I have recently answered a question on C, in which I suggested turning on all compiler warnings.

I thought that I would copy-paste the actual warning that I was sure gcc would have given on compiling the OP's code.

Except it did not work. I boiled it down to this test case which also does not work:

int main() {
        int a; /* not initialised */

        while (a) { /* warn me! */
            a++;
        }

        return 0;
}

I would have bet my last penny on gcc saying:

test.c: In function ‘main’:
test.c:4:6: warning: ‘a’ is used uninitialized in this function   [-Wuninitialized]

 while (a) {
        ^

...and I would have lost. I get no warning whatsoever! And yet if I use if instead of while, why yes, then I get exactly that warning. But with while? Nary a whisper.

I checked out some reports that seemed germane and concluded that while they don't apply, there just might be something done by gcc that makes the warning superfluous in just this one case. I'd like to know what.

Is it because a is initialized to 0? No, because

int main() {
    int a;

    if (a == 0) { printf("a is zero\n"); }

    while (a == 0) { a = printf("a is zero\n"); }

    return 0;
}

gives an error on the if(), but gives no more errors if I comment the if() out. If gcc knew that a was going to be 0, the first if also should have elicited no error.

So what's happening here?

Community
  • 1
  • 1
LSerni
  • 55,617
  • 10
  • 65
  • 107

1 Answers1

3

This is not a bug. It's a quality of implementation issue. If we look at the manual, it states:

Note that there may be no warning about a variable that is used only to compute a value that itself is never used, because such computations may be deleted by data flow analysis before the warnings are printed.

Indeed, the following:

int b = a++;

does elicit a warning.

main.cpp:6:16: warning: variable 'a' is uninitialized when used here [-Wuninitialized]
        while (a) { /* warn me! */
               ^

main.cpp:4:14: note: initialize the variable 'a' to silence this warning
        int a; /* not initialised */
             ^
              = 0

Original example had printf, but that was confusing as it implies relation to the "as-if" rule.

Really, the best thing you can do is:

  • Accept that warning about every possible scenario is equivalent to solving the halting problem

  • Report it to the developers and hope they do something about it

  • Use an alternative. Clang does provide a warning

  • Look at "Better Uninitialized Warnings" from the GCC wiki. Support the project. Keep in mind that there's two sides to the coin. GCC is notorious for bogus warnings as well.

  • To confirm, you're saying the entire lifetime of `a` has no effects and can be optimised away altogether. Interesting to hear how this can affect warning diagnostics! – underscore_d Oct 10 '15 at 00:39
  • @underscore_d that's not necessarily the case, whether it is optimised out or not isn't related to the lack of warning. – teppic Oct 10 '15 at 00:46
  • Yeah, not ideal wording by me. What I meant was the lack of side effects and how I didn't realise some warnings were affected by that. – underscore_d Oct 10 '15 at 00:48
  • fwiw a dupe suggests optimisation might indeed be involved if its output is the input used for flow analysis http://stackoverflow.com/questions/29313855/why-does-gcc-only-sometimes-detect-the-use-of-a-variable-before-its-initializati?rq=1 – underscore_d Oct 10 '15 at 09:03
  • 1
    Actually, this **is** a bug ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=18501 ). To counter your example, I added `int a, b;` and then assigned a to b, and printf'ed b to stdout, and `gcc -W -Wall` did not even twitch. Possibly in C++ mode the behaviour is different. The duplicate answer however suggests to install **clang** for these checks. – LSerni Nov 04 '16 at 19:42