C2y adds the `_Countof` operator which returns the number of elements in
an array. As with `sizeof`, `_Countof` either accepts a parenthesized
type name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
This is being exposed as an extension in earlier C language modes, but
not in C++. C++ already has `std::extent` and `std::size` to cover these
needs, so the operator doesn't seem to get the user enough benefit to
warrant carrying this as an extension.
Fixes#102836
When revisiting a variable, we do that by simply calling visitDecl() for
it, which means it will end up with the same EvalID as the rest of the
evaluation - but this way we end up allowing reads from mutable
variables. Disallow that.
…723)"
This reverts commit 1e2ad6793ac205607e7c809283cf69e1cc36a69a.
Fix the previous commit on big-endian hosts by _not_ falling through to
the `uint8_t` code path.
This returns the type of data in the Block, which might be different
than the type of the expression or declaration we created the block for.
This lets us remove some special cases from CheckNewDeleteForms() and
CheckNewTypeMismatch().
As pointed out by @shafik, this confuses static analysis and most
probably humans as well. Add an assertion to ensure the given array has
at least one element.
Handles #123121
This patch updates `note_constexpr_invalid_cast` diagnostic to use
`enum_select` instead of `select,` improving readability and reducing
reliance on magic numbers in caller sites.
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.
Make the memory representation of boolean vectors in HLSL, vectors of
i32.
Allow boolean swizzling for boolean vectors in HLSL.
Add tests for boolean vectors and boolean vector swizzling.
Closes#91639
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.
getRecord() returns null on array elements, even for composite arrays.
The assertion here was overly restrictive and having an array element as
instance pointer should be fine otherwise.
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.
The APValue we generated for a pointer with a LValueReferenceType base
had an incorrect lvalue path attached.
The attached test case is extracted from libc++'s regex.cpp.