112 Commits

Author SHA1 Message Date
Timm Baeder
36cbd43ae8
[clang][bytecode] Check new/delete mismatch earlier (#147732)
This fixes a mismatch in diagnostic output with the current intepreter.
2025-07-10 07:33:33 +02:00
Rahul Joshi
6cf656eca7
[NFC][Clang][AST] Drop llvm:: in front of ArrayRef/MutableArrayRef (#145207) 2025-06-23 13:10:42 -07:00
Timm Baeder
32fc625a3f
Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (#145014)
…types usi… (#144676)"

This reverts commit 68471d29eed2c49f9b439e505b3f24d387d54f97.

IntegralAP contains a union:
  union {
    uint64_t *Memory = nullptr;
    uint64_t Val;
  };

On 64bit systems, both Memory and Val have the same size. However, on 32
bit system, Val is 64bit and Memory only 32bit. Which means the default
initializer for Memory will only zero half of Val. We fixed this by
zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth)
constructor.


See also the discussion in
https://github.com/llvm/llvm-project/pull/144246
2025-06-20 18:06:01 +02:00
Timm Bäder
68471d29ee Revert "Reapply "[clang][bytecode] Allocate IntegralAP and Floating types usi… (#144676)"
This reverts commit 7c15edb306932e41c159f3d69c161ed0d89d47b7.

This still breaks clang-armv8-quick:
https://lab.llvm.org/buildbot/#/builders/154/builds/17587
2025-06-18 15:17:53 +02:00
Timm Baeder
7c15edb306
Reapply "[clang][bytecode] Allocate IntegralAP and Floating types usi… (#144676)
…ng an allocator (#144246)"

This reverts commit 57828fec760f086b334ce0cb1c465fc559dcaea4.
2025-06-18 14:37:29 +02:00
Timm Bäder
57828fec76 Revert "[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)"
This reverts commit c66be289901b3f035187d391e80e3610d7d6232e.

This breaks the armv8-quick builder:
https://lab.llvm.org/buildbot/#/builders/154/builds/17549
2025-06-17 21:08:23 +02:00
Timm Baeder
c66be28990
[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)
Both `APInt` and `APFloat` will heap-allocate memory themselves using
the system allocator when the size of their data exceeds 64 bits.

This is why clang has `APNumericStorage`, which allocates its memory
using an allocator (via `ASTContext`) instead. Calling `getValue()` on
an ast node like that will then create a new `APInt`/`APFloat` , which
will copy the data (in the `APFloat` case, we even copy it twice).
That's sad but whatever.

In the bytecode interpreter, we have a similar problem. Large integers
and floating-point values are placement-new allocated into the
`InterpStack` (or into the bytecode, which is a `vector<std::byte>`).
When we then later interrupt interpretation, we don't run the destructor
for all items on the stack, which means we leak the memory the
`APInt`/`APFloat` (which backs the `IntegralAP`/`Floating` the
interpreter uses).

Fix this by using an approach similar to the one used in the AST. Add an
allocator to `InterpState`, which is used for temporaries and local
values. Those values will be freed at the end of interpretation. For
global variables, we need to promote the values to global lifetime,
which we do via `InitGlobal` and `FinishInitGlobal` ops.

Interestingly, this results in a slight _improvement_ in compile times:
https://llvm-compile-time-tracker.com/compare.php?from=6bfcdda9b1ddf0900f82f7e30cb5e3253a791d50&to=88d1d899127b408f0fb0f385c2c58e6283195049&stat=instructions:u
(but don't ask me why).

Fixes https://github.com/llvm/llvm-project/issues/139012
2025-06-17 18:31:06 +02:00
Timm Baeder
478bdd8b90
[clang][bytecode] Save Constexpr bit in Function (#142793)
Rename isConstexpr to isValid, the former was always a bad name. Save a
constexpr bit in Function so we don't have to access the decl in
CheckCallable.
2025-06-05 06:38:48 +02:00
Timm Baeder
2e70da3fba
[clang][bytecode] Partially address string literal uniqueness (#142555)
This still leaves the case of the

constexpr auto b3 = name1() == name1();

test from cxx20.cpp broken.
2025-06-03 16:26:31 +02:00
Timm Baeder
722d6b55ed
[clang][bytecode] Only check expr in CheckThis() if we have to (#141951)
Pre C++11, we dont't need to get the value of IsImplicit.
2025-05-29 17:17:59 +02:00
Timm Baeder
4efe7a590d
[clang][bytecode] Simplify diagnoseUnknownDecl if we're not diagnosing (#141910)
See the added comment.

This improves compile times a bit:

https://llvm-compile-time-tracker.com/compare.php?from=ac62f73f19ae9fb415d3fc423949b8d7543e8717&to=0d6cf47197a4ee11cdd1ee4a48ea38a2907c3d45&stat=instructions:u
2025-05-29 13:02:50 +02:00
Timm Baeder
857ffa1915
[clang][bytecode] Recursively start lifetimes as well (#141742)
The constructor starts the lifetime of all the subobjects.
2025-05-28 16:16:00 +02:00
Timm Baeder
294643e4bd
[clang][bytecode] Check lifetime of all ptr bases in placement-new (#141272)
placement-new'ing an object with a dead base object is not allowed, so
we need to check all the pointer bases.
2025-05-24 14:17:26 +02:00
Timm Baeder
319feac43d
[clang][bytecode] Fix AccessKinds in placement new CheckStore() call (#141123)
CheckStore is for assignments, but we're constructing something here, so
pass AK_Construct instead. We already diagnosed the test case, but as an
assignment.
2025-05-23 13:00:57 +02:00
Timm Baeder
32805964fc
[clang][bytecode] Diagnose placement-new'ing to a temporary (#141099)
... that's been created in a different evaluation.
2025-05-23 08:17:22 +02:00
Timm Baeder
d45f1d0827
[clang][bytecode] Fix self-init diagnostics in C++23 (#141044) 2025-05-22 14:26:52 +02:00
Timm Baeder
7cfeedf64a
[clang][bytecode] Change diagnostics for self-initialization (#141006)
Change the diagnostics when reading from the variable we're currently
initializing do be the same as the one the current interpreter emits.
2025-05-22 10:31:39 +02:00
Timm Baeder
572add0601
[clang][bytecode] Diagnose failed constexpr assertions differently (#140000)
Adjust to the new way the ast walker is doing it.
2025-05-19 13:29:09 +02:00
Timm Baeder
9a26dff748
[clang][bytecode] Check dtor calls for one-past-end pointers (#140047) 2025-05-15 15:43:07 +02:00
Timm Baeder
b26adacc85
[clang][bytecode] Check destructors for temporaries (#140039)
Also, increase the EvalID in isPotentialConstantExpr(), since this is
its own evaluation.
2025-05-15 14:34:35 +02:00
Timm Baeder
c14acb7442
[clang][bytecode] Save Immediate bit in Function (#139671)
Otherwise, we have to look at the FunctionDecl at every function call.
2025-05-13 12:56:08 +02:00
Timm Baeder
98763433e6
[clang][bytecode] Optimize enum value range checks (#139672)
Only do the work if we really have to.
2025-05-13 10:55:24 +02:00
Timm Baeder
98d68e49f7
[clang][bytecode][NFC] Remove unused function (#139355) 2025-05-10 07:57:44 +02:00
Timm Baeder
d6f1de3107
[clang][bytecode] Bail out on invalid function declarations (#138503) 2025-05-05 16:24:53 +02:00
Timm Baeder
c51be1be3a
[clang][bytecode] Fix checking for integer overflow (#137962)
We need to evaluate both the True/False expressions of a conditional
operator as well as the LHS/RHS of a binary operator in more cases.
2025-05-01 07:35:33 +02:00
Timm Baeder
f8724bd873
[clang][bytecode] Check live-ness when calling dtors (#137645)
We can't call a destructor on a dead pointer.
2025-04-28 17:47:30 +02:00
Timm Baeder
959905a5ad
[clang][bytecode] Don't create Function instances for builtins (#137618)
Now that we don't use them anymore in InterpBuiltin.cpp and we don't
create frames for them anymore anyway, just don't create Function
instances.
2025-04-28 14:08:42 +02:00
Timm Baeder
e086d7b146
[clang][bytecode] Don't create function frames for builtin calls (#137607)
They don't have local variables etc. so don't create frames for them.
2025-04-28 13:11:15 +02:00
Timm Baeder
60b3a5b7e7
[clang][bytecode] Fix two small builtin_constant_p cases (#137587)
Only accept string literals if we're pointing to the first index and do
accept complex literals.
2025-04-28 09:21:49 +02:00
Timm Baeder
e045d55dd5
[clang][bytecode] Check for global decls in destructors (#137525)
Destructors can't be called on global variables.
2025-04-27 20:02:58 +02:00
Timm Baeder
ef87c3421c
[clang][bytecode] Check for dummy pointers when calling pseudo dtors (#137437) 2025-04-26 05:47:54 +02:00
Timm Baeder
211b51e471
[clang][bytecode] Propagate IsVolatile bit to subobjects (#137293)
For
```c++
  struct S {
    constexpr S(int=0) : i(1) {}
    int i;
  };
  constexpr volatile S vs;
```

reading from `vs.i` is not allowed, even though `i` is not volatile
qualified. Propagate the IsVolatile bit down the hierarchy, so we know
reading from `vs.i` is a volatile read.
2025-04-25 11:23:34 +02:00
Timm Baeder
5eca2ddeba
[clang][bytecode] Don't diagnose const extern reads in CPCE mode (#137285)
They might become constexpr later.
2025-04-25 08:54:34 +02:00
Timm Baeder
3b58a60086
[clang][bytecode] Allow forming pointers to fields of extern globals (#137211)
This should be fine as long as we're not reading from it.

Note that this regresses
CXX/special/class.init/class.inhctor.init/p1.cpp, which used to work
fine with the bytecode interpreter.

That's because this code now fails:

```c++
  struct Param;
  struct A {
    constexpr A(Param);
    int a;
  };

  struct B : A { B(); using A::A; int b = 2; };
  struct Wrap1 : B { constexpr Wrap1(); };
  struct Wrap2 : Wrap1 {};
  extern const Wrap2 b;

  struct Param {
    constexpr Param(int c) : n(4 * b.a + b.b + c) {}
    int n;
  };
```
and reports that the Param() constructor is never a valid constant
expression. But that's true and the current interpeter should report
that as well. It also fails when calling at compile time.
2025-04-25 07:43:33 +02:00
Timm Baeder
1b6cbaa7b6
[clang][bytecode] Refine diagnostics for volatile reads (#136857)
Differentiate between a volarile read via a lvalue-to-rvalue cast of a
volatile qualified subexpression and a read from a pointer with a
volatile base object.
2025-04-23 18:52:35 +02:00
Timm Baeder
c5d59723cb
[clang][bytecode] Reject constexpr-unknown values in CheckStore (#136279) 2025-04-18 12:48:16 +02:00
Timm Baeder
05eafd9f2b
[clang][bytecode] Explicitly mark constexpr-unknown variables as such (#135806)
Instead of trying to figure out what's constexpr-unknown later on.
2025-04-16 09:00:52 +02:00
Timm Baeder
974bda8f61
[clang][bytecode] Reject constexpr-unknown pointers from Inc ops (#135548)
We used to accept c++ as a known value here, causing wrong codegen.
2025-04-13 18:57:55 +02:00
Timm Baeder
fafeaab6d9
[clang][bytecode] Misc TypeidPointer fixes (#135322)
Fix comparing type id pointers, add mor info when print()ing them, use
the most derived type in GetTypeidPtr() and the canonically unqualified
type when we know the type statically.
2025-04-11 10:35:28 +02:00
Oliver Hunt
1cd59264aa
[RFC] Initial implementation of P2719 (#113510)
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-04-10 17:13:10 -07:00
Timm Baeder
02f923f8e4
[clang][bytecode] Classify function pointers as PT_Ptr (#135026)
The Pointer class already has the capability to be a function pointer,
but we still classifed function pointers as PT_FnPtr/FunctionPointer.
This means when converting from a Pointer to a FunctionPointer, we lost
the information of what the original Pointer pointed to.
2025-04-10 06:40:54 +02:00
Timm Baeder
11dd7d98a6
[clang][bytecode] Reject constexpr-unknown values from comparisons (#133701) 2025-03-31 18:53:01 +02:00
Timm Baeder
cb7b10c66e
[clang][bytecode] Fail on mutable reads from revisited variables (#133064)
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.
2025-03-26 12:29:31 +01:00
Timm Baeder
849e5ea94f
[clang][bytecode] Add Descriptor::getDataType() (#132681)
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().
2025-03-24 09:47:52 +01:00
Timm Baeder
49f06075a6
[clang][bytecode] Fix union copy/move operator active check (#132238)
Don't call CheckActive for copy/move operators. They will activate the
union member.
2025-03-20 19:08:55 +01:00
Timm Baeder
2f808dd070
[clang][bytecode] Compile most recent function decl (#131730)
We used to always do this because all calls went through the code path
that calls getMostRecentDecl(). Do it now, too.
2025-03-18 07:29:38 +01:00
Timm Baeder
ca1bde0b91
[clang][bytecode] Check dtor instance pointers for active-ness (#128732)
And diagnose if we're trying to destroy an inactive member of a union.
2025-03-17 19:01:35 +01:00
Timm Baeder
83356f3b62
[clang][bytecode] Compile functions lazily (#131596)
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.
2025-03-17 15:58:35 +01:00
Timm Baeder
d08cf7900d
[clang][bytecode] Implement __builtin_constant_p (#130143)
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.
2025-03-08 06:06:14 +01:00
Timm Baeder
bdbc434498
[clang][bytecode] Ignore function calls with depth > 0... (#129887)
... when checking for a potential constant expression. This is also what
the current interpreter does.
2025-03-05 16:21:03 +01:00