The constant evaluator could try to reference a lambda capture in a
static lambda call operator. Static lambdas can't have captures, so we
simply abort. Either the lambda needs to be made non-static, or the
capture (and reference to it) need to be removed.
Fixes: https://github.com/llvm/llvm-project/issues/74608
This commit introduces support for the MSVC-specific C++11-style
attribute `[[msvc::constexpr]]`, which was introduced in MSVC 14.33.
The semantics of this attribute are enabled only under
MSVC compatibility (`-fms-compatibility-version`) 14.33 and higher.
Additionally, the default value of `_MSC_VER` has been raised to 1433.
The current implementation lacks support for:
- `[[msvc::constexpr]]` constructors (see #72149);
at the time of this implementation, such support would have required
an unreasonable number of changes in Clang.
- `[[msvc::constexpr]] return ::new` (constexpr placement new) from
non-std namespaces (see #74924).
Relevant to: #57696
Increment and decrement are equivalent to adding or subtracting 1. For
the floating-point values these operations depend on the current
rounding mode. Teach constant evaluator to perform ++ and -- according
to the current floating-point environment.
Pull request: https://github.com/llvm/llvm-project/pull/73770
EvaluateAsConstantExpr() uses ::EvaluateInPlace() directly, which does
not use the new interpreter if requested. Do it here, which is the same
pattern we use in EvaluateAsInitializer.
The data size is required for implementing the `memmove` optimization
for `std::copy`, `std::move` etc. correctly as well as replacing
`__compressed_pair` with `[[no_unique_address]]` in libc++. Since the
compiler already knows the data size, we can avoid some complexity by
exposing that information.
This patch converts `StringLiteral::StringKind` to a scoped enum in namespace scope. This enabled forward-declarations of this enum where necessary, e.g. for `preferred_type` annotation for bit-fields.
C language standard defined library functions `iszero`, `issignaling`
and `issubnormal`, which did not have counterparts among clang builtin
functions. This change adds new functions:
__builtin_iszero
__builtin_issubnormal
__builtin_issignaling
They provide builtin implementation for the missing standard functions.
Pull request: https://github.com/llvm/llvm-project/pull/69041
This patch moves `ArraySizeModifier` before `Type` declaration so that it's complete at `ArrayTypeBitfields` declaration. It's also converted to scoped enum along the way.
During constant evaluation when value-initializing a class if the base
class was default-initialized it would undue the previously
zero-initialized class members. This fixes the way we handle default
initialization to avoid initializing over an already initialized member
to an indeterminate value.
Fixes: https://github.com/llvm/llvm-project/issues/69890
Adds a new `__builtin_vectorelements()` function which returns the
number of elements for a given vector either at compile-time for
fixed-sized vectors, e.g., created via `__attribute__((vector_size(N)))`
or at runtime via a call to `@llvm.vscale.i32()` for scalable vectors,
e.g., SVE or RISCV V.
The new builtin follows a similar path as `sizeof()`, as it essentially
does the same thing but for the number of elements in vector instead of
the number of bytes. This allows us to re-use a lot of the existing
logic to handle types etc.
A small side addition is `Type::isSizelessVectorType()`, which we need
to distinguish between sizeless vectors (SVE, RISCV V) and sizeless
types (WASM).
This is the [corresponding
discussion](https://discourse.llvm.org/t/new-builtin-function-to-get-number-of-lanes-in-simd-vectors/73911).
with an explicit parameter.
We tried to read a pointer to a non-existent `This` APValue when
constant-evaluating an explicit object lambda call operator (the `this`
pointer is never set in explicit object member functions)
Fixes#68070
This patch makes clang diagnose extensive cases of consteval if and is_constant_evaluated usage that are tautologically true or false.
This introduces a new IsRuntimeEvaluated boolean flag to Sema::ExpressionEvaluationContextRecord that means the immediate appearance of if consteval or is_constant_evaluated are tautologically false(e.g. inside if !consteval {} block or non-constexpr-qualified function definition body)
This patch also pushes new expression evaluation context when parsing the condition of if constexpr and initializer of constexpr variables so that Sema can be aware that the use of consteval if and is_consteval are tautologically true in if constexpr condition and constexpr variable initializers.
BEFORE this patch, the warning for is_constant_evaluated was emitted from constant evaluator. This patch moves the warning logic to Sema in order to diagnose tautological use of is_constant_evaluated in the same way as consteval if.
This patch separates initializer evaluation context from InitializerScopeRAII.
This fixes a bug that was happening when user takes address of function address in initializers of non-local variables.
Fixes https://github.com/llvm/llvm-project/issues/43760
Fixes https://github.com/llvm/llvm-project/issues/51567
Reviewed By: cor3ntin, ldionne
Differential Revision: https://reviews.llvm.org/D155064
An assertion issue that arose when handling union member access with
virtual base class has been addressed. As pointed out by @zygoloid,
there is no need for further derived-to-base analysis in this instance,
so we can bail out upon encountering a virtual base class. Minor
refinement on the function name as we might not be handling a union.
Reported-By: ormris
Fixes: https://github.com/llvm/llvm-project/issues/65982
Before:
```
array.cpp:319:10: note: read of uninitialized object is not allowed in a constant expression
319 | return aaa;
| ^
```
After:
```
array.cpp:319:10: note: read of uninitialized object is not allowed in a constant expression
319 | return aaa;
| ^~~
```
The width of the APSInt values should be the width of an element.
getCharByteWidth returns the size of an element in _host_ bytes, which
makes the width N times greater, where N is the ratio between target's
CHAR_BIT and host's CHAR_BIT.
This is NFC for in-tree targets because all of them have CHAR_BIT == 8.
Reviewed By: cor3ntin, aaron.ballman
Differential Revision: https://reviews.llvm.org/D154773
Consider the following code:
#include <windows.h>
#include <TraceLoggingActivity.h>
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DEFINE_PROVIDER(
g_hMyComponentProvider,
"SimpleTraceLoggingProvider",
// {0205c616-cf97-5c11-9756-56a2cee02ca7}
(0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));
void test()
{
TraceLoggingFunction(g_hMyComponentProvider);
}
int main()
{
TraceLoggingRegister(g_hMyComponentProvider);
test();
TraceLoggingUnregister(g_hMyComponentProvider);
}
It compiles with MSVC, but clang-cl reports an error:
C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared/TraceLoggingActivity.h(377,30): note: expanded from macro '_tlgThisFunctionName'
#define _tlgThisFunctionName __FUNCTION__
^
.\tl.cpp(14,5): error: cannot initialize an array element of type 'char' with an lvalue of type 'const char[5]'
TraceLoggingFunction(g_hMyComponentProvider);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The second commit is not needed to support above code, however, during isolated tests in ms_predefined_expr.cpp
I found that MSVC accepts code with constexpr, whereas clang-cl does not.
I see that in most places PredefinedExpr is supported in constant evaluation, so I didn't wrap my code with ``if(MicrosoftExt)``.
Reviewed By: cor3ntin
Differential Revision: https://reviews.llvm.org/D158591
The code mistakenly returns the value as evaluated whenever the
temporary is allocated, but not yet evaluated.
I could only reproduce in Clangd and could not come up with an example
that would crash the compiler. Clangd runs more evaluations for hover
than the language would allow.
Reviewed By: kadircet
Differential Revision: https://reviews.llvm.org/D158985
The implementation of __builtin_strncmp and other related builtins function use
getExtValue() to evaluate the size argument. This can cause a crash when the
value does not fit into an int64_t value, which is can be expected since the
type of the argument is size_t.
The fix is to switch to using getZExtValue().
This fixes: https://github.com/llvm/llvm-project/issues/64876
Differential Revision: https://reviews.llvm.org/D158557
BEFORE this patch, compound assignment operator against uninitialized object such as uninit += 1 was diagnosed as subexpression not valid
This patch clarifies the reason for the error by saying that uninit is an uninitialized object.
Fixes https://github.com/llvm/llvm-project/issues/51536
Reviewed By: shafik, tbaeder
Differential Revision: https://reviews.llvm.org/D157855
even if we know what the result is going to be.
There may be side effects we ought not to ignore,
Fixes#64923
Reviewed By: ChuanqiXu
Differential Revision: https://reviews.llvm.org/D158601
BEFORE:
```
overflow.cpp:1:21: warning: overflow in expression; result is -2147483648 with type 'int' [-Winteger-overflow]
1 | int x = __INT_MAX__ + 1 + 3;
| ^
overflow.cpp:2:9: warning: overflow in expression; result is -2147483648 with type 'int' [-Winteger-overflow]
2 | int a = -(1 << 31) + 1;
| ^
```
AFTER:
```
overflow.cpp:1:21: warning: overflow in expression; result is -2147483648 with type 'int' [-Winteger-overflow]
1 | int x = __INT_MAX__ + 1 + 3;
| ~~~~~~~~~~~~^~~
overflow.cpp:2:9: warning: overflow in expression; result is -2147483648 with type 'int' [-Winteger-overflow]
2 | int a = -(1 << 31) + 1;
| ^~~~~~~~~~
```
Reviewed By: tbaeder
Differential Revision: https://reviews.llvm.org/D157383
Since we also have VLST for rvv now, it is not clear to keep using `isVLSTBuiltinType`, so I added prefix SVE to it.
Reviewed By: paulwalker-arm
Differential Revision: https://reviews.llvm.org/D158045
As discussed on #46593 - this enables us to use __lzcnt / __popcnt intrinsics inside constexpr code.
Differential Revision: https://reviews.llvm.org/D157420
This patch fixes the reported regression caused by D146358 through adding notes about an uninitialized base class when we diagnose uninitialized constructor.
This also changes the wording from the old one in order to make it clear that the uninitialized subobject is a base class and its constructor is not called.
Wording changes:
BEFORE: `subobject of type 'Base' is not initialized`
AFTER: `constructor of base class 'Base' is not called`
Fixes https://github.com/llvm/llvm-project/issues/63496
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D153969
For code like:
struct foo { ... };
struct bar { struct foo foo; };
const struct foo my_foo = { ... };
struct bar my_bar = { .foo = my_foo };
Eli Friedman points out the relevant part of the C standard seems to
have some flexibility in what is considered a constant expression:
6.6 paragraph 10:
An implementation may accept other forms of constant expressions.
GCC 8 added support for these, so clang not supporting them has been a
constant thorn in the side of source code portability within the Linux
kernel.
Fixes: https://github.com/llvm/llvm-project/issues/44502
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D76096
This patch adds additional printing of template argument list when the described function is a template specialization.
This can be useful when handling complex template functions in constexpr evaluator.
Reviewed By: cjdb, dblaikie
Differential Revision: https://reviews.llvm.org/D154366
This is a temporary fix (for clang 17) that caps the size of
any array we try to constant evaluate:
There are 2 limits:
* We cap to UINT_MAX the size of ant constant evaluated array,
because the constant evaluator does not support size_t.
* We cap to `-fconstexpr-steps` elements the size of each individual
array and dynamic array allocations.
This works out because the number of constexpr steps already limits
how many array elements can be initialized, which makes this new
limit conservatively generous.
This ensure that the compiler does not crash when attempting to
constant-fold valid programs.
If the limit is reached by a given array, constant evaluation will fail,
and the program will be ill-formed, until a bigger limit is given.
Or, constant folding will fail and the array will be evaluated at runtime.
Fixes#63562
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D155955
As suggested by @efriedma in:
https://reviews.llvm.org/D76096#4370369
This should speed up evaluating whether an expression is constant or
not, but due to the complexity of these two different implementations,
we may start getting different answers for edge cases for which we do
not yet have test cases in-tree (or perhaps even performance regressions
for some cases). As such, contributors have carte blanche to revert if
necessary.
For additional historical context about ExprConstant vs CGExprConstant,
here's snippets from a private conversation on discord:
ndesaulniers:
why do we have clang/lib/AST/ExprConstant.cpp and
clang/lib/CodeGen/CGExprConstant.cpp? Does clang constant fold during
ast walking/creation AND during LLVM codegen?
efriedma:
originally, clang needed to handle two things: integer constant
expressions (the "5" in "int x[5];"), and constant global initializers
(the "5" in "int x = 5;"). pre-C++11, the two could be handled mostly
separately; so we had the code for integer constants in AST/, and the
code for globals in CodeGen/. C++11 constexpr sort of destroyed that
separation, though. so now we do both kinds of constant evaluation on
the AST, then CGExprConstant translates the result of that evaluation
to LLVM IR. but we kept around some bits of the old cgexprconstant to
avoid performance/memory usage regressions on large arrays.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D151587