constant evaluator loses track of most-derived array information when reconstructing `LValue` from `APValue`
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
[Testcase](https://godbolt.org/z/v8fa8e3Kz):
```c++
struct A { int n; };
struct B : A {} b[2];
constexpr int *f() {
// Loses MostDerived array information.
A *p = b;
return &static_cast(p)[1].n;
}
static_assert(f() == &b[1].n);
```
Clang incorrectly rejects:
```console
:10:15: error: static assertion expression is not an integral constant expression
10 | static_assert(f() == &b[1].n);
| ^~~~~~~~~~~~~~
:7:11: note: cannot access base class of pointer past the end of object
7 | return &static_cast(p)[1].n;
| ^
:10:15: note: in call to 'f()'
10 | static_assert(f() == &b[1].n);
| ^~~
```
This is happening because reconstruction of an `LValue` from an `APValue` (specifically, `SubobjectDesignator` construction) is miscomputing the values for the `MostDerivedIsArrayElement` and `MostDerivedArraySize` fields in the case where the most-derived object that the lvalue refers to is an array element, but the lvalue itself is not (that is, when the lvalue refers to a base subobject of an array element).
That's happening here:
https://github.com/llvm/llvm-project/blob/364bed30971df7fb50d7aadfc21f3996a97bf3a4/clang/lib/AST/ExprConstant.cpp#L238-L242
I think deleting that `else` case would be the proper fix here: for a base subobject, we just want to inherit the "most derived" properties (the "is array" flag and array size) from the previous element.
Contributor guide
Research direction
Reproduce the Godbolt testcase, then inspect clang/lib/AST/ExprConstant.cpp around lines 238-242, focusing on SubobjectDesignator reconstruction and its MostDerived array fields. Verify the fix preserves the array-element information for a base subobject and that the static_assert is accepted.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100