195 Commits

Author SHA1 Message Date
Timm Baeder
461e433718
[clang][bytecode] Don't use trunc() to increase APInt bitWidth (#180536)
`FieldDecl::getBitWidthValue()` can return a value higher than the type
size of the bit field. We need to account for that.
2026-02-10 07:53:23 +01:00
Timm Baeder
a8af0901dd
[clang][bytecode] Don't call getOffset on non-block pointers (#179628)
Fixes https://github.com/llvm/llvm-project/issues/177587
2026-02-04 12:39:21 +01:00
Timm Baeder
87e38d3b97
[clang][bytecode][NFC] Add Pointer::canDeref (#179618) 2026-02-04 09:18:23 +01:00
flovent
a9b7b4d957
[clang][bytecode] Fix crash caused by overflow of Casting float number to integer (#177815)
Before this PR evaluation process will stop immediately regradless of
whether it's set to handle overflow,

this will prevent us getting value from stack, which leads to crash(with
or without assertion).

Closes  #177751.
2026-01-26 07:54:22 +01:00
Timm Baeder
de8126d62a
[clang][bytecode] Fix mulc/divc op for IntegralAP types (#177565)
We need to allocate those.

Fixes https://github.com/llvm/llvm-project/issues/176740
2026-01-23 13:04:39 +01:00
Timm Baeder
323bb14349
[clang][bytecode] Finish support for msvc::constexpr (#177388)
Keep track of whether an `InterpFrame` is allowed to call
`msvc::constexpr` functions via two new opcodes.
2026-01-23 11:25:21 +01:00
Timm Baeder
7f39d92d56
[clang][bytecode][NFC] Move some opcode impls to the source file (#177543)
They aren't templated, so move them to Interp.cpp to make the header
file a bit shorter.
2026-01-23 11:10:48 +01:00
Timm Baeder
d904de0806
[clang][bytecode] Fix a diagnostic discrepancy (#177384)
The current interpreter does _not_ evaluate function calls when checking
for a potential constant expression.

However, it _does_ evaluate the initializers of constructors. In the
bytecode interpreter, this is harder because we compile the initializers
and the body of a constructor all in the same function.

Add a special opcode that we emit after the constructor initializers and
that aborts when we're checking for a potential constant expression.
2026-01-23 08:36:03 +01:00
Timm Baeder
ab366170db
[clang][bytecode] Add lifetime information for primitive array elements (#173333)
Double the allocated size of the `InitMap` and use the second half for
lifetime information.
2026-01-21 09:41:35 +01:00
Timm Baeder
a15adf5b9b
[clang][bytecode][NFC] Add Pointer::stripBaseCasts() helper (#176875)
We do this is in a few places, so add a helper function for it.
2026-01-20 11:21:22 +01:00
Kartik
7dc2cd4c68
[clang][bytecode] Handle corner condition for sign negation (#176390)
RHS = -RHS works for most cases, however, the behaviour when RHS is
INTXX_MIN is undefined. In these particular case(s), we should use
INTXX_MAX instead.

Fixes #176271.
2026-01-20 06:24:40 +01:00
Timm Baeder
6cbf9cef58
[clang][bytecode] Check for non-block pointers in CopyArray (#175710)
Fixes https://github.com/llvm/llvm-project/issues/175674
2026-01-13 08:28:37 +01:00
Timm Baeder
4da37d3295
[clang][bytecode] Check for non-trivial default ctors in unions (#174745)
When activating a union member, none of the unions in that path can have
a non-trivial constructor. Unfortunately, this is something we have to
do when evaluating the bytecode, not while compiling it.
2026-01-08 06:07:12 +01:00
Timm Baeder
24f0c26dd0
[clang][bytecode] Check inc/dec operations for constness (#174276) 2026-01-05 10:59:38 +01:00
Timm Baeder
4ecca392d2
[clang][bytecode] Use record layout in Pointer::computeOffsetForComparison() (#172322)
Our internal representation for records does not include things like
alignment of the fields or padding bits, so we can't only rely on those
values, not even for just comparing two pointers.

Try to look up the offsets from the `ASTRecordLayout` instead.

Fixes https://github.com/llvm/llvm-project/issues/172165

---------

Co-authored-by: Shafik Yaghmour <shafik.yaghmour@intel.com>
2025-12-24 08:16:01 +01:00
Timm Baeder
db557bee1e
[clang][bytecode][NFC] Add Block::getBlockDesc<T>() (#172218)
Which returns the block-level descriptor. This way we don't have to do
the reinterpret_cast dance everywhere.
2025-12-15 09:21:41 +01:00
Timm Bäder
773a6a9cc8 Revert "[clang][bytecode] Allocate InitMaps via Program/InterpState allocators (#170272)"
This reverts commit 8fe38c4c9c71c7a86ecdba476ee5bae4c02c0dfe.

This breaks the clang-armv7-2stage build bot:
https://lab.llvm.org/buildbot/#/builders/79/builds/2531
2025-12-09 06:19:09 +01:00
Timm Baeder
8fe38c4c9c
[clang][bytecode] Allocate InitMaps via Program/InterpState allocators (#170272)
Save them as a pointer intead of using a shared_ptr. This we we can use
the pointer integer value to differentiate the "no initmap yet" and "all
values initialzed" cases.

This regresses one test case in const-eval.c, but as it turns out, that
only worked coincidentally before.
2025-12-06 06:37:45 +01:00
Timm Baeder
6696e0c8f8
[clang][bytecode] Remove double diagnostic emission (#169658)
We emit this diagnostic from CheckPointerToIntegralCast() already, so
remove the emission from CastPointerIntegral().
2025-11-27 07:15:23 +01:00
Timm Baeder
95f0fab7fa
[clang][bytecode] Fix conditional operator scoping wrt. local variables (#169030)
We used to create a scope for the true- and false expression of a
conditional operator. This was done so e.g. in this example:

```c++
  struct A { constexpr A(){}; ~A(); constexpr int get() { return 10; } }; // all-note 2{{declared here}}
  static_assert( (false ? A().get() : 1) == 1);
```

we did _not_ evaluate the true branch at all, meaning we did not
register the local variable for the temporary of type `A`, which means
we also didn't call it destructor.

However, this breaks the case where the temporary needs to outlive the
conditional operator and instead be destroyed via the surrounding
`ExprWithCleanups`:
```
constexpr bool test2(bool b) {
  unsigned long __ms = b ? (const unsigned long &)0 : __ms;
  return true;
}
static_assert(test2(true));
```
Before this patch, we diagnosed this example:
```console
./array.cpp:180:15: error: static assertion expression is not an integral constant expression
  180 | static_assert(test2(true));
      |               ^~~~~~~~~~~
./array.cpp:177:24: note: read of temporary whose lifetime has ended
  177 |   unsigned long __ms = b ? (const unsigned long &)0 : __ms;
      |                        ^
./array.cpp:180:15: note: in call to 'test2(true)'
  180 | static_assert(test2(true));
      |               ^~~~~~~~~~~
./array.cpp:177:51: note: temporary created here
  177 |   unsigned long __ms = b ? (const unsigned long &)0 : __ms;
      |                                                   ^
1 error generated.
```
because the temporary created for the true branch got immediately
destroyed.

The problem in essence is that since the conditional operator doesn't
create a scope at all, we register the local variables for both its
branches, but we later only execute one of them, which means we should
also only destroy the locals of one of the branches.

We fix this similar to clang codgen's `is_active` flag: In the case of a
conditional operator (which is so far the only case where this is
problematic, and this also helps minimize the performance impact of this
change), we make local variables as disabled-by-default and then emit a
`EnableLocal` opcode later, which marks them as enabled. The code
calling their destructors checks whether the local was enabled at all.
2025-11-24 07:34:48 +01:00
Timm Baeder
90e1391d18
[clang][bytecode] Check pointers in GetPtrField{,Pop} (#167335)
The pointer needs to point to a record.

Fixes https://github.com/llvm/llvm-project/issues/166371
2025-11-17 08:24:44 +01:00
Timm Baeder
70eb4b0a60
[clang][bytecode] Fix diagnosing subtration of zero-size pointers (#167839)
We need to get the element type size at bytecode generation time to
check. We also need to diagnose this in the LHS == RHS case.
2025-11-13 09:58:43 +01:00
Timm Baeder
a8a0ffba73
[clang][bytecode] Check source pointer for bitcast validity (#166907)
Unfortunately this is more dynamic than anticipated.

Fixes https://github.com/llvm/llvm-project/issues/165006
2025-11-10 08:17:08 +01:00
Timm Baeder
6fac21e404
[clang][bytecode] Avoid copies with elidable CXXConstructExprs (#166931)
To fix the newly added cwg6.cpp.
2025-11-08 05:30:01 +01:00
Timm Baeder
14c76437ee
[clang][bytecode] Check types when loading values (#165385)
We need to allow BitCasts between pointer types to different prim types,
but that means we need to catch the problem at a later stage, i.e. when
loading the values.

Fixes https://github.com/llvm/llvm-project/issues/158527
Fixes https://github.com/llvm/llvm-project/issues/163778
2025-11-05 16:02:19 +01:00
camc
b2da8eff96
[clang][bytecode] Fix crash when array index is past end of array in C (#165186)
Fixes #165090

Make sure to reject invalid array pointer offsets in C.

Co-authored-by: camc <pushy-crop-cartel@duck.com>
2025-10-27 15:51:36 +01:00
Timm Baeder
d7e40f3e71
[clang][bytecode] Call CheckStore() before activating pointers (#165235)
We used to do this the other way around to work around an awkwardness
with CheckStore, namely that we shouldn't check pointers for being
activated when activating them.

Add a parameter to CheckStore instead and call CheckStore() _before_
activating and initializing the pointers in the respective opcode
implementations.

Fixes https://github.com/llvm/llvm-project/issues/164975
2025-10-27 14:41:21 +01:00
Timm Baeder
954a719056
[clang][bytecode] Fix unsigned wraparound behavior with bitfields (#164445)
and inc/dec operations. We need to truncate the new value to the
bitfield bitwidth.
2025-10-22 11:01:33 +02:00
Timm Baeder
c8c5a382a2
[clang][bytecode] Move shared interp functions to InterpHelpers.h (#164215)
This drastically reduces the preprocessed size of Context.cpp and
InterpBuiltin.cpp.
2025-10-21 14:25:59 +02:00
Timm Baeder
f44f83a35d
[clang][bytecode] Reject typeid pointers from OffsetHelper (#163793) 2025-10-17 14:51:16 +02:00
term-est
cf55dfbc5a
[clang][bytecode] Fix null Descriptor dereference in ArrayElemPtrPop (#163386)
Fixes #163127
2025-10-16 09:47:42 +02:00
Tsche
ec2d6add36
[clang] introduce constexpr step limit opt-out (#160440)
To address @AaronBallman's feedback from
https://github.com/llvm/llvm-project/pull/143785 this patch implements
an explicit opt-out for `-fconstexpr-steps` by setting
`-fconstexpr-steps=0`.

This does not change any defaults, but gives users an easy way to opt
out of this limit altogether (and instead let the compiler reach the
system's resource limits).

Currently users set `constexpr-steps` to some arbitrary high number (and
I mean _arbitrary_ - see the tables in the previous PR). This isn't
actually opting out of the limit though - you're still bound by the
upper bound of the counter's type. If you have enough resources to
evaluate more than 18446744073709551615 steps that's bad news.

In any case, `=0` conveys the intent clearer. This is in line with how
we handle other flags, ie `-ftemplate-backtrace-limit` or
`-ferror-limit`.
2025-10-13 11:53:06 -04:00
Timm Baeder
a5e30f8350
[clang][bytecode][NFC] Avoid creating pointers in CopyArray op (#163042)
Since these are all primitive arrays, use the new `elem()` and
`initializeElement()` functions.
2025-10-12 08:11:12 +02:00
Timm Baeder
c750487292
[clang][bytecode] Diagnose volatile writes (#160350) 2025-09-28 07:21:40 +02:00
Timm Baeder
010f96aa91
[clang][bytecode] Use existing Descriptor local in InitElem op (#160535)
Instead of going the way through `Pointer::isUnknownSizeArray()`.
2025-09-24 16:45:49 +02:00
Timm Baeder
d94a8282fb
[clang][bytecode] Don't crash on a null Descriptor (#160506)
... for dynamic memory allocation. This happens when the requested array
size is too large.

Fixes #152951
2025-09-24 14:48:38 +02:00
Timm Baeder
b98f0b8209
[clang][bytecode] Use stack offsets for This/RVO ptrs (#160285)
Instead of keeping the `Pointer`s itself in `InterpFrame`, just save
them as offsets and use stackRef<>() when we need them.
2025-09-24 10:30:51 +02:00
Timm Baeder
2155f17d39
[clang][bytecode] Optimize InitElem{,Pop} (#159084)
Try harder to avoid creating a new `Pointer` for the element.
2025-09-17 09:27:07 +02:00
Timm Baeder
29c55d0f7b
[clang][bytecode] Improve error detection in BitCastPrim op (#158575)
Reject bitcasts to pointer types unless it's to `nullptr_t` and always
reject bitcasts to member pointer types.


Fixes #156174
2025-09-16 10:02:18 +02:00
Timm Baeder
7b0d910026
[clang][bytecode] Check for dummy pointers in CopyArray op (#158543)
They can't be written to or read from.

Fixes #158535
2025-09-15 08:33:34 +02:00
Timm Baeder
9b00a58cbd
[clang][bytecode] Use bytecode interpreter in EvaluateAsLValue (#158038)
Set the EvalMode on InterpState and abort when initalizing a global
temporary, like the current interpreter does. The rest is just plumbing
in EvaluateAsLValue.

Fixes #157497
2025-09-11 13:29:44 +02:00
Timm Baeder
94d5c54a4f
[clang][bytecode] Don't update temporary in InitGlobalTemp* (#158022)
We can save ourselves the conversion to an APValue here since we will do
that later in updateGlobalTemporaries() anyway.
2025-09-11 12:32:58 +02:00
Samarth Narang
3b150fb128
[clang][bytecode] Handle negative array sizes in constexpr new instead of asserting (#155737)
This patch fixes a crash in the constexpr interpreter when evaluating
`new T[n]` with a negative element count.

Fixes https://github.com/llvm/llvm-project/issues/152904
2025-08-29 08:28:40 -04:00
Timm Baeder
2ea5ec78db
[clang][bytecode] Fix a crash in Destroy op (#154695)
The local we're destroying might've been created for an expression, in
which case asDecl() on the DeclDesc returns nullptr.

Fixes #152958
2025-08-21 13:23:57 +02:00
Timm Baeder
c9bb3bdbca
[clang][bytecode] Fix a crash with typeid pointers (#154692)
That code is from a time when typeid pointers didn't exist. We can get
there for non-block, non-integral pointers, but we can't meaningfully
handle that case. Just return false.

Fixes #153712
2025-08-21 13:13:02 +02:00
Timm Baeder
21bd3a7fa8
[clang][bytecode] Check for unknown size array pointers in InitField* (#154689)
This can happen when the base pointer is an unknown size array, where
!isOnePastEnd(), but isPastEnd().

Fixes #153990
2025-08-21 13:01:45 +02:00
Timm Baeder
e16ced3ef4
[clang][bytecode] Diagnose one-past-end reads from global arrays (#154484)
Fixes #154312
2025-08-20 10:34:44 +02:00
Matheus Izvekov
91cdd35008
[clang] Improve nested name specifier AST representation (#147835)
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-09 05:06:53 -03:00
Timm Baeder
193995d5a2
[clang][bytecode] Handle more invalid member pointer casts (#152546) 2025-08-07 19:24:01 +02:00
Timm Baeder
c869ef6ebc
[clang][bytecode] Refactor Check* functions (#152300)
... so we don't have to create Pointer instances when we don't need
them.
2025-08-07 11:32:39 +02:00