llvm / llvm/llvm-project

constant evaluator loses track of most-derived array information when reconstructing `LValue` from `APValue`

Open
#223,064 8 comments 0 reactions 0 assignees View on GitHub
clang:frontend constexpr good first issue rejects-valid
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.