aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-08-09[clang] Improve nested name specifier AST representation (#147835)Matheus Izvekov1-26/+43
This is a major change on how we represent nested name qualifications in the AST. * The nested name specifier itself and how it's stored is changed. The prefixes for types are handled within the type hierarchy, which makes canonicalization for them super cheap, no memory allocation required. Also translating a type into nested name specifier form becomes a no-op. An identifier is stored as a DependentNameType. The nested name specifier gains a lightweight handle class, to be used instead of passing around pointers, which is similar to what is implemented for TemplateName. There is still one free bit available, and this handle can be used within a PointerUnion and PointerIntPair, which should keep bit-packing aficionados happy. * The ElaboratedType node is removed, all type nodes in which it could previously apply to can now store the elaborated keyword and name qualifier, tail allocating when present. * TagTypes can now point to the exact declaration found when producing these, as opposed to the previous situation of there only existing one TagType per entity. This increases the amount of type sugar retained, and can have several applications, for example in tracking module ownership, and other tools which care about source file origins, such as IWYU. These TagTypes are lazily allocated, in order to limit the increase in AST size. This patch offers a great performance benefit. It greatly improves compilation time for [stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for `test_on2.cpp` in that project, which is the slowest compiling test, this patch improves `-c` compilation time by about 7.2%, with the `-fsyntax-only` improvement being at ~12%. This has great results on compile-time-tracker as well: ![image](https://github.com/user-attachments/assets/700dce98-2cab-4aa8-97d1-b038c0bee831) This patch also further enables other optimziations in the future, and will reduce the performance impact of template specialization resugaring when that lands. It has some other miscelaneous drive-by fixes. About the review: Yes the patch is huge, sorry about that. Part of the reason is that I started by the nested name specifier part, before the ElaboratedType part, but that had a huge performance downside, as ElaboratedType is a big performance hog. I didn't have the steam to go back and change the patch after the fact. There is also a lot of internal API changes, and it made sense to remove ElaboratedType in one go, versus removing it from one type at a time, as that would present much more churn to the users. Also, the nested name specifier having a different API avoids missing changes related to how prefixes work now, which could make existing code compile but not work. How to review: The important changes are all in `clang/include/clang/AST` and `clang/lib/AST`, with also important changes in `clang/lib/Sema/TreeTransform.h`. The rest and bulk of the changes are mostly consequences of the changes in API. PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just for easier to rebasing. I plan to rename it back after this lands. Fixes #136624 Fixes https://github.com/llvm/llvm-project/issues/43179 Fixes https://github.com/llvm/llvm-project/issues/68670 Fixes https://github.com/llvm/llvm-project/issues/92757
2025-08-08[Headers][X86] Enable constexpr handling for pmulhw/pmulhuw intrinsics (#152540)Simon Pilgrim1-1/+19
This patch updates the pmulhw/pmulhuw builtins to support constant expression handling - extending the VectorExprEvaluator::VisitCallExpr handling code that handles elementwise integer binop builtins. Hopefully this can be used as reference patch to show how to add future target specific constexpr handling with minimal code impact. I've also enabled pmullw constexpr handling (which are tagged on #152490) as they all use very similar tests. I've also had to tweak the MMX -> SSE2 wrapper as undefs are not permitted in constexpr shuffle masks Fixes #152524
2025-08-06[clang][ExprConst] Consider integer pointers of value 0 nullptr (#150164)Timm Baeder1-5/+9
When casting a 0 to a pointer type, the IsNullPtr flag was always set to false, leading to weird results like a pointer with value 0 that isn't a null pointer. This caused ```c++ struct B { const int *p;}; template<B> void f() {} template void f<B{nullptr}>(); template void f<B{fold(reinterpret_cast<int*>(0))}>(); ``` to be valid code, since nullptr and (int*)0 aren't equal. This seems weird and GCC doesn't behave like this.
2025-08-05[clang] Fix constant evaluation of member pointer access into sibling class. ↵keinflue1-0/+21
(#150829) HandleMemberPointerAccess considered whether the lvalue path in a member pointer access matched the bases of the containing class of the member, but neglected to check the same for the containing class of the member itself, thereby ignoring access attempts to members in direct sibling classes. Fixes #150705. Fixes #150709.
2025-08-04[AST] Use llvm::iterator_range::empty (NFC) (#151904)Kazu Hirata1-1/+1
2025-08-01[clang][ExprConst] Call `FastEvaluateAsRValue` in `isCXX11ConstantExpr` ↵Timm Baeder1-13/+20
(#151466) This was one case where we didn't call `FastEvaluateAsRValue` before going through `EvaluateAsRValue`. Also replace the `EvalResult` parameter with an `APValue` one, since `FastEvaluateAsRVaule` only needs that. Small gains: https://llvm-compile-time-tracker.com/compare.php?from=112af8e62e734938547d50eeb7b416c8dd666f45&to=b2ea804b9e22b7f37eb1b07b01c0a8057275fe4a&stat=instructions:u
2025-08-01[clang][ExprConst] Remove Loc param (#151461)Timm Baeder1-31/+13
The Loc param to these functions was weird and not always set in error cases. It wasn't reliable to use. This was almost entirely unused inside of clang and the one call site that used the returned source location doesn't make a difference in practice.
2025-07-30[clang] Forbid reinterpret_cast of function pointers in constexpr. (#150557)Eli Friedman1-4/+13
This has been explicitly forbidden since C++11, but somehow the edge case of converting a function pointer to void* using a cast like `(void*)f` wasn't handled. Fixes #150340 .
2025-07-24[clang] Fix const eval of constexpr-unknown relational comparisons. (#150088)Eli Friedman1-2/+4
Like in other places, ignore the reference type of the base. (It might make sense to refactor this at some point.) Fixes #150015.
2025-07-20[clang][bytecode] Use in Expr::tryEvaluateStrLen() (#149677)Timm Baeder1-0/+4
Fixes #138475
2025-07-19[Clang] Be less strict about diagnosing null pointer dereference. (#149648)Corentin Jabot1-3/+7
In #143667, we made constant evaluation fail on `*null_ptr`, as this is UB. However, `&(*(foo*)0)` seems to be a common pattern, which made #143667 too disruptive. So instead of failing the evaluation, we note the UB, which let clang recovers when checking for constant initialization. Fixes #149500
2025-07-19[clang][bytecode] Use bytecode interpreter in isPotentialConstantExprU… ↵Timm Baeder1-0/+5
(#149462) …nevaluated Fake a function call to the given function and evaluate the given expression as if it was part of that function call. Fixes #149383
2025-07-17[clang] Fix potential constant expression checking with constexpr-unknown. ↵Eli Friedman1-4/+7
(#149227) 071765749a70b22fb62f2efc07a3f242ff5b4c52 improved constexpr-unknown diagnostics, but potential constant expression checking broke in the process: we produce diagnostics in more cases. Suppress the diagnostics as appropriate. This fix affects -Winvalid-constexpr and the enable_if attribute. (The -Winvalid-constexpr diagnostic isn't really important right now, but it will become important if we allow constexpr-unknown with pre-C++23 standards.) Fixes #149041. Fixes #149188.
2025-07-16[Clang] Diagnose forming references to nullptr (#143667)Corentin Jabot1-19/+85
Per [decl.ref], > Because a null pointer value or a pointer past the end of an object does not point to an object, a reference in a well-defined program cannot refer to such things. Note this does not fixes the new bytecode interpreter. Fixes #48665
2025-07-15[clang] Fix pointer comparisons between pointers to constexpr-unknown (#147663)Eli Friedman1-6/+4
A constexpr-unknown reference can be equal to an arbitrary value, except values allocated during constant evaluation. Fix the handling. The standard is unclear exactly which pointer comparisons count as "unknown" in this context; for example, in some cases we could use alignment to prove two constexpr-unknown references are not equal. I decided to ignore all the cases involving variables not allocated during constant evaluation. While looking at this, I also spotted that there might be issues with lifetimes, but I didn't try to address it.
2025-07-11Follow up on #147623Owen Pan1-0/+1
2025-07-11[clang] Fix copy/paste error in vector `__builtin_elementwise_{add,sub}_sat` ↵Connector Switch1-2/+2
implementation. (#147973) Closes #147891.
2025-07-09Address a handful of C4146 compiler warnings where literals can be replaced ↵Alex Sepkowski1-2/+2
with std::numeric_limits (#147623) This PR addresses instances of compiler warning C4146 that can be replaced with std::numeric_limits. Specifically, these are cases where a literal such as '-1ULL' was used to assign a value to a uint64_t variable. The intent is much cleaner if we use the appropriate std::numeric_limits value<Type>::max() for these cases. Addresses #147439
2025-07-09[clang] Implement consteval for captured structured bindings. (#147615)Eli Friedman1-14/+14
127bf44385424891eb04cff8e52d3f157fc2cb7c implemented most of the infrastructure for capturing structured bindings in lambdas, but missed one piece: constant evaluation of such lambdas. Refactor the code to handle this case. Fixes #145956.
2025-07-08[clang][CompundLiteralExpr] Don't defer evaluation for CLEs (#137163)kadir çetinkaya1-41/+49
Previously we would defer evaluation of CLEs until LValue to RValue conversions, which would result in creating values within wrong scope and triggering use-after-frees. This patch instead eagerly evaluates CLEs, within the scope requiring them. This requires storing an extra pointer for CLE expressions with static storage. Fixes https://github.com/llvm/llvm-project/issues/137165
2025-07-07[clang] Improve constexpr-unknown diagnostics. (#146288)Eli Friedman1-42/+27
APValue::ConstexprUnknown() constructs a broken LValue that doesn't have an lvalue path, which confuses later error handling. It turns out we don't actually use the result of createConstexprUnknownAPValues for anything, so just stop using it. Just construct the LValue directly when we need it. Make findCompleteObject emit errors more aggressively; allowing it to succeed for constexpr-unknown objects leads to weird states where it succeeds, but doesn't return a well-formed object. Delete the check for constexpr-unknown in dynamic_cast handling: it's not necessary, and breaks with the other changes in this patch. These changes allow us to produce proper diagnostics when something fails to be evaluated, instead of just printing a generic top-level error without any notes.
2025-06-23Reland "[Modules] Record whether VarDecl initializers contain side effects" ↵Henrik G. Olsson1-0/+6
(#145447) This reverts commit 329ae86 and adds an early exit for EvaluateInPlace when the expression's type is null.
2025-06-23[NFC][Clang][AST] Drop `llvm::` in front of `ArrayRef`/`MutableArrayRef` ↵Rahul Joshi1-4/+3
(#145207)
2025-06-13Remove delayed typo expressions (#143423)Aaron Ballman1-1/+0
This removes the delayed typo correction functionality from Clang (regular typo correction still remains) due to fragility of the solution. An RFC was posted here: https://discourse.llvm.org/t/rfc-removing-support-for-delayed-typo-correction/86631 and while that RFC was asking for folks to consider stepping up to be maintainers, and we did have a few new contributors show some interest, experiments show that it's likely worth it to remove this functionality entirely and focus efforts on improving regular typo correction. This removal fixes ~20 open issues (quite possibly more), improves compile time performance by roughly .3-.4% (https://llvm-compile-time-tracker.com/?config=Overview&stat=instructions%3Au&remote=AaronBallman&sortBy=date), and does not appear to regress diagnostic behavior in a way we wouldn't find acceptable. Fixes #142457 Fixes #139913 Fixes #138850 Fixes #137867 Fixes #137860 Fixes #107840 Fixes #93308 Fixes #69470 Fixes #59391 Fixes #58172 Fixes #46215 Fixes #45915 Fixes #45891 Fixes #44490 Fixes #36703 Fixes #32903 Fixes #23312 Fixes #69874
2025-06-11[C++20][Modules] Fix false compilation error with constexpr (#143168)Dmitry Polukhin1-1/+2
Use declaresSameEntity when evaluating constexpr to avoid resetting computed union value due to using different instances of the merged field decl.
2025-06-06[clang] Check constexpr int->enum conversions consistently. (#143034)Eli Friedman1-17/+3
In 8de51375f12d91675a18d17f262276e65f43fbe0 and related patches, we added some code to avoid triggering -Wenum-constexpr-conversion in some cases. This isn't necessary anymore because -Wenum-constexpr-conversion doesn't exist anymore. And the checks are subtly wrong: they exclude cases where we actually do need to check the conversion. This patch gets rid of the unnecessary checks.
2025-06-05[Clang] Run destructors of variables declared in the second part of a `for` ↵Vincent1-1/+5
loop during constant evaluation (#140278) Within the condition statement of the for block, the destructor doesn't get called when evaluating compile time constants. Resolves #139818
2025-06-05[Clang] Fix constant eval of assignment operators with an explicit object ↵Corentin Jabot1-23/+41
parameter (#142964) Fixes #142835
2025-06-03[clang] Don't evaluate the initializer of constexpr-unknown parameters. ↵Eli Friedman1-1/+6
(#142498) If we see a parameter of reference type that isn't part of the frame, don't try to evaluate its default argument. Just treat it as a constexpr-unknown value. Fixes #141114. Fixes #141858.
2025-05-28[AArch64] Rename AArch64SVEACLETypes.def and add base SVE_TYPE.David Green1-1/+1
2025-05-27[HLSL] Implement `SpirvType` and `SpirvOpaqueType` (#134034)Cassandra Beckley1-0/+1
This implements the design proposed by [Representing SpirvType in Clang's Type System](https://github.com/llvm/wg-hlsl/pull/181). It creates `HLSLInlineSpirvType` as a new `Type` subclass, and `__hlsl_spirv_type` as a new builtin type template to create such a type. This new type is lowered to the `spirv.Type` target extension type, as described in [Target Extension Types for Inline SPIR-V and Decorated Types](https://github.com/llvm/wg-hlsl/blob/main/proposals/0017-inline-spirv-and-decorated-types.md).
2025-05-26[clang][ExprConst][NFC] Only call getExprLoc() once (#141473)Timm Baeder1-3/+4
It's potentially costly, so only do it once.
2025-05-19[clang] fix constexpr-unknown handling of self-references. (#132990)Eli Friedman1-42/+31
Usually, in constant evaluation, references which are local to the evaluation have to be initialized before they're accessed. However, there's one funny special case: the initializer of a reference can refer to itself. This generally ends up being undefined behavior if it's used in an evaluated context, but it isn't otherwise forbidden. In constant evaluation, this splits into two cases: global variables, and local variables in constexpr functions. This patch handles both of those cases. (Local variables tends to trip other errors in most cases, but if you try hard enough, you can get an accepts-invalid.) Fixes #131330 .
2025-05-15[Clang][AST] Fix HandleLValueBase to deal with references (#140105)Shafik Yaghmour1-1/+5
Since P2280R4 Unknown references and pointers was implemented, HandleLValueBase now has to deal with referneces: D.MostDerivedType->getAsCXXRecordDecl() will return a nullptr if D.MostDerivedType is a ReferenceType. The fix is to use getNonReferenceType() to obtain the Pointee Type if we have a reference. Fixes: https://github.com/llvm/llvm-project/issues/139452
2025-05-14[clang] Save ShuffleVectorExpr args as ConstantExpr (#139709)Timm Baeder1-1/+1
The passed indices have to be constant integers anyway, which we verify before creating the ShuffleVectorExpr. Use the value we create there and save the indices using a ConstantExpr instead. This way, we don't have to evaluate the args every time we call getShuffleMaskIdx().
2025-05-14Better diagnostics when assertion fails in `consteval` (#130458)JJ Marr1-2/+15
Take this piece of code: ```cpp #include <cassert> consteval int square(int x) { int result = x * x; assert(result == 42); return result; } void test() { auto val = square(2); } ``` The assertion will fail, and `clang++` will output (https://godbolt.org/z/hjz3KbTTv): ```cpp <source>:10:14: error: call to consteval function 'square' is not a constant expression 10 | auto val = square(2); | ^ <source>:5:3: note: non-constexpr function '__assert_fail' cannot be used in a constant expression 5 | assert(result == 42); | ^ /usr/include/assert.h:95:9: note: expanded from macro 'assert' 95 | : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) | ^ <source>:10:14: note: in call to 'square(2)' 10 | auto val = square(2); | ^~~~~~~~~ /usr/include/assert.h:69:13: note: declared here 69 | extern void __assert_fail (const char *__assertion, const char *__file, | ^ 1 error generated. Compiler returned: 1 ``` This is confusing because it implies that the issue was using an assertion in a constant-evaluted context, and not that the assertion failed (`assert()` is OK in constant evaluation). This PR changes the error message to: ```cpp test.cpp:10:14: error: call to consteval function 'square' is not a constant expression 10 | auto val = square(2); | ^ test.cpp:5:3: note: assertion failed in consteval context: 'result == 42' 5 | assert(result == 42); | ^ /nix/store/lw21wr626v5sdcaxxkv2k4zf1121hfc9-glibc-2.40-36-dev/include/assert.h:102:9: note: expanded from macro 'assert' 102 | : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \ | ^ test.cpp:10:14: note: in call to 'square(2)' 10 | auto val = square(2); | ^~~~~~~~~ 1 error generated.```
2025-05-09Revert "[clang][ExprConst] Check for array size of initlists (#138673)"Timm Bäder1-8/+0
This reverts commit d35ad58859c97521edab7b2eddfa9fe6838b9a5e. This breaks the clang build: https://lab.llvm.org/buildbot/#/builders/132/builds/1033 /home/buildbot-worker/bbroot/clang-riscv-rva23-evl-vec-2stage/stage2/lib/Target/RISCV/RISCVGenGlobalISel.inc:1512:44: note: cannot allocate array; evaluated array bound 2431270 exceeds the limit (1048576); use '-fconstexpr-steps' to increase this limit
2025-05-09[clang][ExprConst] Check for array size of initlists (#138673)Timm Baeder1-0/+8
Fixes #138653
2025-05-08[clang][ExprConstant] Bail out on invalid lambda capture inits (#138832)Timm Baeder1-1/+1
Fixes https://github.com/llvm/llvm-project/issues/138824
2025-05-05[clang][bytecode] Use bytecode interpreter in EvaluateCharRangeAsString ↵Timm Baeder1-1/+5
(#138461) This was always using the ast walker.
2025-05-02[Clang] Fix handling of reference types in tryEvaluateBuiltinObjectSize ↵cor3ntin1-3/+5
(#138247) The order of operation was slightly incorrect, as we were checking for incomplete types *before* handling reference types. Fixes #129397 --------- Co-authored-by: Erich Keane <ekeane@nvidia.com>
2025-04-24Fix a crash in constant evaluation of ExtVectorElementExprs (#136771)Akira Hatanaka1-1/+4
Handle the case where the base expression is a pointer to a vector type. rdar://149223362
2025-04-23Eval string one past end reland (#137091)Henrik G. Olsson1-2/+7
Relands #137078 after updating clang/test/AST/ByteCode/cxx20.cpp to account for diagnostic outputs that differ between Linux and macOS.
2025-04-23Revert "[ConstEval] Fix crash when comparing strings past the end" (#137088)Henrik G. Olsson1-7/+2
Reverts llvm/llvm-project#137078
2025-04-23[ConstEval] Fix crash when comparing strings past the end (#137078)Henrik G. Olsson1-2/+7
When `ArePotentiallyOverlappingStringLiterals`, added in https://github.com/llvm/llvm-project/pull/109208, compares string literals it drops the front of the string with the greatest offset from its base pointer. The number of characters dropped is equal to the difference between the two strings' offsets from their base pointers. This would trigger an assert when the resulting offset is past the end of the object. Not only are one-past-the-end pointers legal constructs, the compiler should not crash even when faced with illegal constructs. rdar://149865910
2025-04-19[clang] Use llvm::append_range (NFC) (#136448)Kazu Hirata1-4/+2
2025-04-17[clang][ExprConst] Diagnose ptr subs with non-zero offset (#135938)Timm Baeder1-3/+0
The attached test case was missing the note.
2025-04-10[RFC] Initial implementation of P2719 (#113510)Oliver Hunt1-6/+8
This is a basic implementation of P2719: "Type-aware allocation and deallocation functions" described at http://wg21.link/P2719 The proposal includes some more details but the basic change in functionality is the addition of support for an additional implicit parameter in operators `new` and `delete` to act as a type tag. Tag is of type `std::type_identity<T>` where T is the concrete type being allocated. So for example, a custom type specific allocator for `int` say can be provided by the declaration of void *operator new(std::type_identity<int>, size_t, std::align_val_t); void operator delete(std::type_identity<int>, void*, size_t, std::align_val_t); However this becomes more powerful by specifying templated declarations, for example template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); template <typename T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t);); Where the operators being resolved will be the concrete type being operated over (NB. A completely unconstrained global definition as above is not recommended as it triggers many problems similar to a general override of the global operators). These type aware operators can be declared as either free functions or in class, and can be specified with or without the other implicit parameters, with overload resolution performed according to the existing standard parameter prioritisation, only with type parameterised operators having higher precedence than non-type aware operators. The only exception is destroying_delete which for reasons discussed in the paper we do not support type-aware variants by default.
2025-03-27[C2y] Implement WG14 N3369 and N3469 (_Countof) (#133125)Aaron Ballman1-0/+50
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
2025-03-25[clang] Placement new error when modifying consts (#132460)marius doerner1-0/+9
Raise an error when placement new is used to modify a const-qualified variable in a constexpr function. Fixes #131432