GCC 11.x令人烦恼的解析+不一致的错误(重新声明为不同的符号类型),这是GCC错误吗



从GCC 4.7.1到GCC 11.1:,以下代码编译没有问题

constexpr int SomeValue = 0;
void test () {
void (SomeValue) ();
}

在GCC 11.x上,它失败:

<source>:4:23: error: 'void SomeValue()' redeclared as different kind of entity
4 |     void (SomeValue) ();
|                       ^
<source>:1:15: note: previous declaration 'constexpr const int SomeValue'
1 | constexpr int SomeValue = 0;
|               ^~~~~~~~~

但是错误";重新声明为不同种类的实体";对我来说似乎很奇怪:除了模棱两可的解析可能性之外,范围是不同的。此外,自4.7.1(包括11.x(以来,这些测试都在GCC的所有版本上编译,即使AFAIK每一个都将SomeValue重新定义为"1";不同类型的实体":

constexpr int SomeValue = 0;
void test1 () { typedef void (SomeValue) (); }
void test2 () { double SomeValue;            }
void test3 () { using SomeValue = char *;    }
void test4 () { void (* SomeValue) ();       }
void test5 () { struct SomeValue { };        }
void test6 () { enum class SomeValue { };    }

作为一个相对不那么荒谬的例子,这个代码也以类似的方式从11.x开始失败:

constexpr int SomeValue = 0;
struct SomeClass {
explicit SomeClass (int) { }
void operator () () { }
};
void test () {
SomeClass(SomeValue)();
}

尽管在这种情况下,它前面有一个令人烦恼的解析警告,在11.x之前也不存在(警告在这里但不在上面的事实是有意义的,警告在11.x以前没有出现的事实是有趣的(:

<source>: In function 'void test()':
<source>:9:25: warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]
9 |     SomeClass(SomeValue)();
|                         ^~
<source>: At global scope:
<source>:9:26: error: 'SomeClass SomeValue()' redeclared as different kind of entity
9 |     SomeClass(SomeValue)();
|                          ^
<source>:1:15: note: previous declaration 'constexpr const int SomeValue'
1 | constexpr int SomeValue = 0;
|               ^~~~~~~~~
Compiler returned: 1

但是等等!还有更多

这段代码——由于与上面相同的解析模糊性,我本以为在11.x上会失败——在所有版本的GCC(包括11.x(上编译得很好:

constexpr int SomeValue = 0;
auto closure = [] (int) {
return [] () { };
};
void test () { 
closure(SomeValue)(); // <-- doesn't cause any problems
}

没有任何警告或任何东西。

所以。。。这是怎么回事?为什么CCD_ 2仅仅是一个问题;重新声明为不同种类的实体";在这些特定的情况下,并且只有在GCC 11.1之后,为什么closure(SomeValue)()没有遇到与SomeClass(SomeValue)()相同的问题?

还有什么变化?GCC在这里正确吗?这是GCC 11.x中引入的一个新错误吗?或者可能是在11.x中最终修复的一个旧错误?或者根本不是一个bug,其他东西也发生了变化?

我很难想出一个一致的解释。

不同之处在于,您的第一个代码片段声明了一个全局存在的函数;所有其他声明都是本地实体的
(请注意,即使声明有效,也不能调用该函数,因为它不可能存在。(

在最后一个代码段中,closure不是类型,因此它不能是声明。

最新更新