The following reproducer does not work in clang with C++20 right now. If D128248 is applied, clang will show an error about the initializer not being a constant expression. If it is not applied, clang will crash because and assertion is hit.
struct Foo {
int a;
constexpr Foo()
: a(get_int()) {
}
constexpr int get_int() {
return 5;
}
};
static constexpr Foo bar[2][1] = {
{{}},
};
godbolt: Compiler Explorer (assertions are not enabled here)
So, I went looking why this happens. When assertions are enabled, clang ultimately runs into an assertion because all APValue
accessors check for e.g. isArray()
etc. which simply check that this->Kind == Array
etc., however, when the above code is compiled, Kind
is a garbage value.
When one tries hard enough, a debugger will reveal that Kind
is set to a garbage value in APValue::~APValue()
when called in expandArray()
.
expandArray()
is a function in ExprConstant.cpp
which takes an array APValue
, creates a new one, swaps all the values and expands the array by filling it with the arrayâs array-filler: llvm-project/ExprConstant.cpp at main ¡ llvm/llvm-project ¡ GitHub
So, notably, all elements of the Array
parameter of expandArray()
are replaced and thus cease to exist.
One of the callers of expandArray()
is findSubobject()
: llvm-project/ExprConstant.cpp at main ¡ llvm/llvm-project ¡ GitHub, this passes *O
as Array
, which in our case is simply the Obj.Value
given by the Obj
parameter. Note here that expandArray
modifies Obj.Value
, even though âfindSubobjectâ doesnât sound like it would modify anything.
In the reproducer above, this is a problem because the Obj
passed to findSubobject
can come from findCompleteObject
, which in our case return the APValue
for the full bar
array: llvm-project/ExprConstant.cpp at main ¡ llvm/llvm-project ¡ GitHub
So⌠while evaluating one of the elements of bar
, the APValue
for bar
is completely redone in expandArray
, which kind of breaks everything.
Iâve tried to modify findSubobject
to not modify anything but it seems like a lot of the code (seemingly implicitly) depends on this behavior.
Does anyone have a better idea on how to fix this?
CC @zygoloid @AaronBallman @shafik
Thanks