You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
An explicit destructor call in an assumption or in the operand of __builtin_constant_p ends the lifetime of an object during constant evaluation #503
During constant evaluation, an explicit destructor call in an evaluation whose result is discarded (the expression of an assumption, or the operand of __builtin_constant_p) ends the lifetime of an object created outside of that evaluation. The object is then treated as uninitialized afterward:
structT {
int v = 1;
constexpr~T() {}
};
constexprintassume_dtor() {
T t;
[[assume((t.~T(), true))]];
return t.v;
}
static_assert(assume_dtor() == 1); // Error: access to uninitialized object.constexprintconstant_p_dtor() {
T t;
(void)__builtin_constant_p((t.~T(), 1));
return t.v;
}
static_assert(constant_p_dtor() == 1); // Error: access to uninitialized object.
(Compiled with --c++23 --g++.)
The expression of an assumption is not evaluated ([dcl.attr.assume]), so assume_dtor() should be 1; g++ 16.1 and clang 21 accept it. For __builtin_constant_p, EDG doesn't keep other side effects of the operand: With t.v = 2 instead of t.~T(), both functions return 1 (as with clang; g++ instead performs the side effects of the operand of __builtin_constant_p, so it rejects constant_p_dtor and returns 2 with the assignment). So the end of the lifetime is the one effect of such an evaluation that persists.
This isn't specific to exceptions, but it came up in the review of #495: An explicit call of the destructor of a std::exception_ptr created outside of such an evaluation would end its lifetime the same way.
Activity