Clang-12 中的错误?“case 值不是常量表达式”

Tho*_*ein 12 c++ clang clang++ c++17

我在 Clang-12 中偶然发现了一个奇怪的编译错误。下面的代码在 GCC 9 中编译得很好。这是编译器中的错误还是我的代码存在实际问题并且 GCC 太宽容了?

#include<atomic>

enum X {
        A
};

class U {
        public:
        std::atomic<X> x;
        U() { x = A; }
};

template<typename T>
class V : public U {
        public:
        V() {
                switch(x) {
                        case A:
                        break;
                }
        }
};

int main() {
        V<void> v;
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我删除该行template<typename T>并只编写V v;而不是V<void> v;. x如果我将其设为非原子性,问题也会消失。我的编译命令是:

clang++-12 test.cpp -std=c++17 -o test
Run Code Online (Sandbox Code Playgroud)

我得到以下编译器输出:

test.cpp:18:9: error: case value is not a constant expression
                        case A:
                             ^
test.cpp:17:10: warning: enumeration value 'A' not handled in switch [-Wswitch]
                switch(x) {
                       ^
test.cpp:25:10: note: in instantiation of member function 'V<void>::V' requested here
        V<void> v;
                ^
1 warning and 1 error generated.
Run Code Online (Sandbox Code Playgroud)

use*_*522 5

对我来说看起来像一个错误。修改case Acase nullptr给出以下错误消息(在模板定义上):

error: no viable conversion from 'std::nullptr_t' to 'std::atomic<X>'
Run Code Online (Sandbox Code Playgroud)

按照问题中的建议将类模板变成一个类,然后给出

error: value of type 'std::nullptr_t' is not implicitly convertible to 'int'
Run Code Online (Sandbox Code Playgroud)

后一条消息是正确的。当在某种条件下使用类类型时,switch它们应该根据上下文隐式转换为整型或枚举类型,然后进行提升。这里应该使用std::atomic<X>的转换函数,将其转换为X,然后提升为int

该语句是否出现在模板中并不重要。

x基类是不依赖的,因此直接引用没有的成员this->也可以。

Ato的转换std::atomic<X>不会是常量表达式,这可能是诊断的来源。

是一个开放的 Clang 错误报告,是另一个可能相关的错误报告。

实际上,尽管提到的两个错误报告仍然处于开放状态,但自 Clang 10 以来,它们提供的测试代码似乎可以正常工作。在我看来,您问题中使用基类的变体是该修复错过的特殊情况。