8

我注意到g++抱怨有点过于严格crossed initialization,我想知道为什么这些误报错误不能仅仅通过在编译时查看程序的 SSA 形式来删除。

让我举一个非常简单的例子:

#include <cstdlib>

int main ()
{
  goto end;

  int i = 0; // unused variable declaration

 end:
  return EXIT_SUCCESS;
}

使用g++ -Wall -Wextra -o example1 example1.cc( g++4.8.1) 编译时,编译器会给出以下错误消息:

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]

因此,它会在实际上没有风险的情况下引发错误,因为该变量未使用(编译器显然拥有这两种信息并且无法将其结合起来以推断该错误是误报)。

更奇怪的是,我希望 LLVM 在分析程序时更有效。所以,我用(3.4)clang++在这个简单的例子上尝试了(LLVM )。而且,我得到了同样的错误信息:clang++ -Wall -Wextra -o example1 example1.ccclang++

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.

所以,我很确定我在这里遗漏了一些重要的东西,这个问题使得检测这种误报比我更难。但是,我不知道它是什么。或者也许,C++ 规范明确规定必须是这样的。

如果有人有想法,请随时分享!

编辑gcc:我还在 C (或)中编译了完全相同的代码clang,并且它运行良好,只是警告说它i是一个未使用的变量。因此,它强化了这样一个事实,即这更有可能与 C++ 规范相关联,而不是在编译时检测到此问题的问题。

4

2 回答 2

10

编译器没有任何问题。根据标准,您的代码格式不正确。

在您的特定情况下,标准的要求可能不是必需的,并且可以允许跳转并且编译器可以创建有效代码。然而,这只是因为变量的初始化int i没有副作用。

您可以通过简单地将跳转部分包含在其自己的范围内来使您的代码有效:

#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;
}
于 2013-08-07T10:25:07.783 回答
8

这是不允许的,因为您可能会为未正确构造的对象调用析构函数。诚然,int它没有构造函数或析构函数,但它使所有类型的对象都“公平”。从技术上讲,标签上的某些东西end:可能正在使用i,并且通过使规则变得严格,它可以防止机器不得不检查每个单独的代码路径(这成为一个“停止问题”)。

于 2013-08-07T10:21:44.840 回答