gcc和clang在表达式是否为常量求值的问题上存在分歧

gcc and clang disagree on whether expression is constant evaluated

本文关键字:问题 存在 常量 clang 表达式 是否 gcc      更新时间:2023-10-16

对于以下程序:

struct S { int i; };
constexpr S f() { 
return std::is_constant_evaluated() ? S{1} : S{0}; 
}
int main() {
S s = f();
return s.i;
}

gcc返回0,clang返回1。演示

我不认为f的评估是在需要不断评估的环境中进行的,所以我认为clang在这里是错误的。还是相反?或者两个结果都有效?

我们要寻找的要求是,如果一个表达式的求值结果明显为常量,这在[expr.const]/14中定义,即:

  • 一个常量表达式,或
  • constexpr-if语句([stmt.if](的条件,或
  • 立即调用,或
  • 代入原子约束表达式以确定是否满足的结果([temp.contr.atomic](,或
  • 在常量表达式中可用或具有常量初始化的变量的初始值设定项

这些条件中的前四个显然不成立。

对于最后一个,我们的变量在常量表达式中不可用,因为它既不是constexpr,也没有const限定的积分/枚举类型。这就是第五个条件的前半部分。

对于最后一个的最后一部分,我们需要确定是否有常量初始化(不要与常量初始化混淆(。这个定义在[basic.start.static]/2中,强调我的:

如果具有静态或线程存储持续时间的变量或临时对象被常量初始化([expr.const](,则执行常量初始化

但是s而不是一个具有静态或线程存储持续时间的变量,因此没有常量初始化,因此最后一个条件的最后一部分也不成立。

因此,这些条件都不成立,并且在OP中,std::is_constant_evaluated()应该返回false,这是一个clang错误。