在持续评估期间读取超出其生命周期的变量是否可诊断?
Is reading a variable outside its lifetime during constant evaluation diagnosable?
如果读取一个超出其生命周期的变量,是否应该期望 in constant evaluation 的可靠失败?
例如:
constexpr bool g() {
int * p = nullptr;
{
int c = 0;
p = &c;
}
return *p == 0;
};
int main() {
static_assert( g() );
}
此处 Clang 因错误停止
read of object outside its lifetime is not allowed in a constant expression
但是 GCC 默默地接受程序 (Demo)。
两个编译器都在他们的权利范围内,还是GCC也必须编译失败?
GCC 丢球了。
[expr.const]
5 An expression E is a core constant expression unless the
evaluation of E, following the rules of the abstract machine
([intro.execution]), would evaluate one of the following:
- ...
- an operation that would have undefined behavior as specified in [intro] through [cpp];
- ...
通过悬挂指针进行的间接操作具有未定义的行为。
[basic.stc.general]
4 When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.
所以g()
的调用可能不是常量表达式,也可能不会出现在static_assert
的条件中,它必须是常量求值
程序格式错误。
以上引用来自C++20标准草案,但C++17也有。
Shall one expect a reliable failure of in constant evaluation if it reads a variable outside of its lifetime?
是的,但您的示例不一定会这样做。它的行为是实现定义的。
当带有变量c
的块退出时([basic.stc.auto]/1), the value of p
becomes an invalid pointer value ([basic.stc.general]/4)。
计算 *p
时,左值到右值的转换 ([conv.lval]) 应用于 p
。 [conv.lval]/3 说:
The result of the conversion is determined according to the following rules:
...
— Otherwise, if the object to which the glvalue refers contains an invalid pointer value, the behavior is implementation-defined.
所以。
Are both compilers within their rights, or GCC must fail the compilation as well?
AFAIK 这两个实现都没有在这里定义它的行为,但我认为理论上可以这样定义它,即转换和其余评估都不会使 g()
不是常量表达式。
如果读取一个超出其生命周期的变量,是否应该期望 in constant evaluation 的可靠失败?
例如:
constexpr bool g() {
int * p = nullptr;
{
int c = 0;
p = &c;
}
return *p == 0;
};
int main() {
static_assert( g() );
}
此处 Clang 因错误停止
read of object outside its lifetime is not allowed in a constant expression
但是 GCC 默默地接受程序 (Demo)。
两个编译器都在他们的权利范围内,还是GCC也必须编译失败?
GCC 丢球了。
[expr.const]
5 An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
- ...
- an operation that would have undefined behavior as specified in [intro] through [cpp];
- ...
通过悬挂指针进行的间接操作具有未定义的行为。
[basic.stc.general]
4 When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.
所以g()
的调用可能不是常量表达式,也可能不会出现在static_assert
的条件中,它必须是常量求值
程序格式错误。
以上引用来自C++20标准草案,但C++17也有。
Shall one expect a reliable failure of in constant evaluation if it reads a variable outside of its lifetime?
是的,但您的示例不一定会这样做。它的行为是实现定义的。
当带有变量c
的块退出时([basic.stc.auto]/1), the value of p
becomes an invalid pointer value ([basic.stc.general]/4)。
计算 *p
时,左值到右值的转换 ([conv.lval]) 应用于 p
。 [conv.lval]/3 说:
The result of the conversion is determined according to the following rules:
...
— Otherwise, if the object to which the glvalue refers contains an invalid pointer value, the behavior is implementation-defined.
所以。
Are both compilers within their rights, or GCC must fail the compilation as well?
AFAIK 这两个实现都没有在这里定义它的行为,但我认为理论上可以这样定义它,即转换和其余评估都不会使 g()
不是常量表达式。