Introduce a trait to determine the number of bindings that would be
produced by
```cpp
auto [...p] = expr;
```
This is necessary to implement P2300
(https://eel.is/c++draft/exec#snd.concepts-5), but can also be used to
implement a general get<N> function that supports aggregates
`__builtin_structured_binding_size` is a unary type trait that evaluates
to the number of bindings in a decomposition
If the argument cannot be decomposed, a sfinae-friendly error is
produced.
A type is considered a valid tuple if `std::tuple_size_v<T>` is a valid
expression, even if there is no valid `std::tuple_element`
specialization or suitable `get` function for that type.
Fixes#46049
Create the Function* handles for all functions we see, but delay the
actual compilation until we really call the function. This speeds up
compile times with the new interpreter a bit.
This implements the R2 semantics of P0963.
The R1 semantics, as outlined in the paper, were introduced in Clang 6.
In addition to that, the paper proposes swapping the evaluation order of
condition expressions and the initialization of binding declarations
(i.e. std::tuple-like decompositions).
This is similar to what the current interpreter is doing - the
FoldConstant RAII object surrounds the entire HandleConditionalOperator
call, which means the condition and both TrueExpr or FalseExpr.
Use the regular code paths for interpreting.
Add new instructions: `StartSpeculation` will reset the diagnostics
pointers to `nullptr`, which will keep us from reporting any diagnostics
during speculation. `EndSpeculation` will undo this.
The rest depends on what `Emitter` we use.
For `EvalEmitter`, we have no bytecode, so we implement `speculate()` by
simply visiting the first argument of `__builtin_constant_p`. If the
evaluation fails, we push a `0` on the stack, otherwise a `1`.
For `ByteCodeEmitter`, add another instrucion called `BCP`, that
interprets all the instructions following it until the next
`EndSpeculation` instruction. If any of those instructions fails, we
jump to the `EndLabel`, which brings us right before the
`EndSpeculation`. We then push the result on the stack.
This happens a lot with `if constexpr` with a condition based on a
template param. In those cases, the condition is a ConstantExpr with a
value already set, so we can use that and ignore the other branch.
…tExpr
If the ImplicitValueInitExpr is of incomplete array type, we ignore it
in its Visit function. This is a special case here, so pull out the
element type and zero the elements.
This used to cause certain std::range tests in libc++ to be diagnosed as
modifying a const-qualified field, because we set the IsConst flag to
true unconditionally. Check the type instead.
For `new A[N]{1,2,3}`, we need to allocate N elements of type A, and
initialize the first three with the given InitListExpr elements.
However, if N is larger than 3, we need to initialize the remaining
elements with the InitListExpr array filler.
Similarly, for `new A[N];`, we need to initilize all fields with the
constructor of A. The initializer type is a CXXConstructExpr of
IncompleteArrayType in this case, which we can't generally handle.
Make lifetime management more explicit. We're only using this for
CXXPseudoDestructorExprs for now but we need this to handle
std::construct_at/placement-new after destructor calls later anyway.
Call `EvaluateAsInitializer()` explicitly here, so we don't abort the
evaluation of the `DeflRefExpr` just because the initializer of that
global variable failed.
See the comment in Compiler<>::VisitCXXThisExpr.
We need to mark the InitList explicitly, so we later know what to refer
to when the init chain is active.
Add it as another kind of pointer, saving both a `Type*` for the result
of the typeid() expression as well as one for the type of the typeid
expression.