Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overkilling "crosses initialization of variable" error in C++?

Tags:

c++

g++

clang++

I noticed that g++ complain a bit too strictly about crossed initialization and I wonder why these false-positive errors could not be removed just by looking at the SSA form of the program while compiling.

Let me give a very simple example:

#include <cstdlib>

int main ()
{
  goto end;

  int i = 0; // unused variable declaration

 end:
  return EXIT_SUCCESS;
}

When compiled with g++ -Wall -Wextra -o example1 example1.cc (g++ 4.8.1), the compiler gives the following error message:

example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
  end:
  ^
example1.cc:6:8: error:   from here [-fpermissive]
   goto end;
        ^
example1.cc:8:7: error:   crosses initialization of ‘int i’
   int i = 0;
       ^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]

So, it will raise an error where there is actually no risk because the variable is unused (the compiler obviously has both information and cannot combine it to deduce that the error is a false-positive).

More strange, I hoped that LLVM was more efficient at analyzing a program. So, I tried clang++ (LLVM) on this simple example with clang++ -Wall -Wextra -o example1 example1.cc (clang++ 3.4). And, I got about the same error message:

example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable]
  int i = 0;
      ^
example1.cc:6:3: error: goto into protected scope
  goto end;
  ^
example1.cc:8:7: note: jump bypasses variable initialization
  int i = 0;
      ^
1 warning and 1 error generated.

So, I am pretty sure that I am missing something important here, a problem that make the detection of this false-positive harder than I though. But, I do not know what is it. Or maybe, the C++ specification specifically says that it must be like this.

If somebody has an idea, feel free to share !

Edit: I also compiled the exact same code in C (gcc or clang), and it went fine just with the warning about i being an unused variable. So, it reinforce the fact that this is more likely linked to the specification of C++ and not a problem detecting this issue at compile time.

like image 572
perror Avatar asked Aug 07 '13 10:08

perror


2 Answers

There is nothing wrong with the compilers. Your code is ill-formed according to the standard.

In your particular case, the requirement of the standard may not be necessary and the jump could be allowed and the compiler could create valid code. However, this is only because the initialisation of the variable int i has no side effects.

You can make your code valid by simply enclosing the jumped section in its own scope:

#include <cstdlib>

int main ()
{
  goto end;
  {
    int i = 0; // unused variable declaration
  }
end:
  // cannot use i here, as it's not defined.
  return EXIT_SUCCESS;
}
like image 159
Walter Avatar answered Nov 20 '22 14:11

Walter


This is disallowed because potentially you'd call destructors for objects that aren't properly constructed. Admittedly, int doesn't have constructor or destructor, but it's making it "fair" for all types of objects. And technically, something at label end: could be using i, and by making the rule strict, it prevents the machine having to check every single code-path (which becomes a "halting problem").

like image 8
Mats Petersson Avatar answered Nov 20 '22 15:11

Mats Petersson