why clang -Wempty-body doesn't detect this case?

Viewed 1096

After answering Xcode- C programming - While loop, I stopped making theoric answers and installed clang on my Windows box to check if it's really better than gcc in the warning diagnostics department.

I'm using -Wempty-body in clang to compile this code, which is wrong because:

  • the while instruction ends with a semicolon, possible typo after long hours ending lines with semicolons...: infinite loop
  • same thing for if statement, making the test useless

wrong code:

int main(void)
{
   char c=1;
   while (c);
   --c;
   if (c);
}

I tried to compile it with clang (5.0.0 x64 windows):

output:

S:\c>clang -Wempty-body test.c
test.c:8:10: warning: if statement has empty body [-Wempty-body]
   if (c);
         ^

So empty if is detected while while isn't.

Now I'm wrapping the decrement instruction in a block after the while:

int main(void)
{
   char c=1;
   while (c);
   { --c; }
   if (c);
}

now it seems to detect both properly:

test.c:6:10: warning: if statement has empty body [-Wempty-body]
   if (c);
test.c:4:13: warning: while loop has empty body [-Wempty-body]
   while (c);

note: gcc wasn't able to see either while bug, so clang is still clearly superior in terms of warning detection (see also why am I not getting an "used uninitialized" warning from gcc in this trivial example?)

What's the heuristics behind this? Is that a bug?

1 Answers

It's to avoid too many false positives. In general, if (expr); never makes sense, but while (expr); need not be an error, because expr's side effects could cause the expression to switch from true to false. For instance,

void processAllElements() {
  while (tryProcessNextElement());
}

Here's how the source explains it:

// `for(...);' and `while(...);' are popular idioms, so in order to keep
// noise level low, emit diagnostics only if for/while is followed by a
// CompoundStmt, e.g.:
//    for (int i = 0; i < n; i++);
//    {
//      a(i);
//    }
// or if for/while is followed by a statement with more indentation
// than for/while itself:
//    for (int i = 0; i < n; i++);
//      a(i);
Related