在某些C ++代码(为GCC编写)上运行git bisect
时,我遇到了由
#include <stdio.h>
int main() {
for (int i = 0; i < 10; ++i) {
long i = 0;
printf("%ld\n", i);
}
return 0;
}
这段代码,我相信,完全标准的C99(gcc -std=c99
编译得很好),但g++
因i
的重新声明而失败。答案https://stackoverflow.com/a/12351531/560450在这个问题上引用了C ++ 11标准:
6.4 / 2条件规则既适用于选择语句,也适用于for和while语句
6.4 / 3如果在由条件控制的子语句的最外层块中重新声明名称,则声明 重申这个名字是不正确的。
在for-init语句中声明的6.5.3 / 1名称与条件中声明的名称在同一声明区域中
因此,我不再对为什么这是非法的C ++感到好奇。 :-)我只想把它编译好!
我看了G ++与语言方言相关的选项。根据{{3}},
如果指定了
-ffor-scope
,则在a中声明变量的范围 for-init-statement 仅限于‘for’
循环本身,如指定的那样 按C ++标准。如果指定了-fno-for-scope
,则范围为。{1}} 在 for-init-statement 中声明的变量扩展到了 封闭范围,与旧版本的G ++和其他版本一样 (传统)C ++的实现。
这是我能找到的唯一一个远程相关的声音选项。奇怪的是,将-fno-for-scope
传递给g++
会使示例编译;即使使用-Wall -Wextra
也没有任何警告。但是,回到我想编译的代码,这个选项会产生很多错误,因为在 for-init-statement 中初始化的变量现在扩展了范围。显然,这不是解决方案。
只是为了澄清:我不打算用C ++编译器编译C99代码,这是愚蠢的。我有一些C ++代码; git blame
告诉重新声明的行是2001年的。我想编译一个标记为2011年发布的提交,因此,我认为它当时没有被破坏。
如果不进行修改,我可以做些什么来编译?目前,我选择了一个重命名违规变量的提交,但我更愿意将CXXFLAGS
中的内容传递给configure
。更一般地说,g++
为什么(或确实)-fno-for-scope
有这种行为和重新声明?
编辑:好吧,可能我应该更加明确。事实上我有一些2001年的代码形式,今天就被打破只是为了设置一些背景。当然,存储库的当前master
编译时没有任何编译器技巧。但是,我感兴趣的是我如何使g++
在历史上表现得像,因为有一个压倒性的概率,即有问题的提交被标记,g++
接受了这种代码。
EDIT2:在使用-fdump-tree-original
之后,问题基本上变成了:是否有任何C ++标准或非标准C ++实现(在GCC中,最好是)在for-init-statement
中声明的变量与循环体或周围代码的范围不同?