Description
Clang fails to compile this code :
https://godbolt.org/z/qvxGcPx6x
struct A {
A();
};
template <class T>
struct opt
{
union Data {
constexpr Data() : x{} {}
constexpr ~Data() {}
char x;
T data;
};
constexpr opt() : data{} {}
constexpr ~opt() { if (engaged) data.data.~T(); }
Data data;
bool engaged = false;
};
consteval void foo()
{
opt<A> a;
}
int main()
{
foo();
}
With the error non-literal type 'opt<A>' cannot be used in a constant expression
(in C++23, in C++20 the message is slightly different). opt<A>
is not considered a literal type because of the implementation of CXXRecordDecl::isLiteral :
llvm-project/clang/include/clang/AST/DeclCXX.h
Line 1457 in ae5d639
which does not take into account that the CXXRecordDecl in question might be an union, in which case the type is literal if at least one of its member is literal. Perhaps the meaning of the bitfield hasNonLiteralTypeFieldsOrBases
should change when the Decl is an union? since it does not seems to serve any other purposes than to detect whether the type is literal or not.
(this causes problem with the constexpr-isation of std::format
which i'm currently working on)