60 Commits

Author SHA1 Message Date
Timm Bäder
c2f75c7159 [clang][Interp] Handle CXXDefaultInitExpr of composite type 2024-03-18 12:59:56 +01:00
Timm Bäder
a4b39f6515 [clang][Interp] Lazily visit const-qualified static data members in C++ 2024-03-17 18:07:51 +01:00
Timm Bäder
447691333f [clang][Interp] Don't suppress diagnostics for undefined+external funcs
Calling them should still generate a diagnostic.
2024-03-15 16:43:43 +01:00
Timm Bäder
9563746d35 [clang][Interp] Diagnose uninitialized global variables explicitly
There used to be some diagnostic differences between the new
interpreter and the old one.
2024-02-20 14:20:17 +01:00
Timm Bäder
e98abc3ea0 [clang][Interp] Emit dtors when ignoring CXXConstructExprs
The comment says we should emit destructors, but we didn't.
2024-02-19 09:48:50 +01:00
Timm Bäder
6a8ab12930 [clang][Interp] Properly emit call ops to invalid functions
Just like everywhere else, we can't just abort compilation because
a function is invalid. We need to emit the Call op and let later
interpretation handle the failure.

This fixes a long standing FIXME comment.
2024-02-15 20:17:51 +01:00
Timm Bäder
0d9decc669 [clang][Interp] Handle invalid CXXCtorInitializer expressions
Their type might be a null type, in which case we need to abort here.
2024-02-09 09:20:41 +01:00
Timm Bäder
fb6ef42339 [clang][Interp][NFC] Convert records test to verify=expected,both style 2024-02-08 15:52:56 +01:00
Timm Bäder
06774d6bbf [clang][Interp] Handle CXXInheritedCtorInitExprs
We need to forward all arguments of the current function and
call the ctor function.
2024-02-08 15:36:07 +01:00
Timm Bäder
d4a2c7f952 [clang][Interp] Fix record initialization from temporary in initlist 2024-02-07 16:09:49 +01:00
Timm Baeder
4e7cf1b1ed
[clang][Interp] Add an EvaluationResult class (#71315)
Add an `EvaluationResult` class. This contains the result either as a
`Pointer` or as a `APValue`.

This way, we can inspect the result of the evaluation and diagnose
problems with it (e.g. uninitialized fields in global initializers or
pointers pointing to things they shouldn't point to).
2024-01-19 10:08:03 +01:00
Timm Baeder
819bd9e39b
[clang][Interp] IndirectMember initializers (#69900)
We need to look at the chain of declarations to initialize the right
field.
2024-01-18 16:25:05 +01:00
Timm Bäder
826fe84a2c [clang][Interp][NFC] Remove outdated FIXME comment
Virtual desturctors are already supported and tested in
AST/Interp/records.cpp.
2024-01-15 12:03:59 +01:00
Timm Baeder
ba11d314a6
[clang][Interp] Only diagnose null field access in constant contexts (#69223)
Looks like this should work as long as we don't dereference the value.
2023-10-26 16:15:29 +02:00
Shafik Yaghmour
b8e06933a2
[Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (#70150)
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
2023-10-25 10:18:40 -07:00
Timm Bäder
311f725d9a [clang][Interp] Create only globals when initializing a global variable
For this code:

struct O {
  int &&j;
};

O o1(0);

The generated AST for the initializer of o1 is:

VarDecl 0x62100006ab08 <array.cpp:119:3, col:9> col:5 o1 'O':'O' parenlistinit
`-ExprWithCleanups 0x62100006b250 <col:7, col:9> 'O':'O'
  `-CXXParenListInitExpr 0x62100006b210 <col:7, col:9> 'O':'O'
    `-MaterializeTemporaryExpr 0x62100006b1f0 <col:8> 'int' xvalue
      `-IntegerLiteral 0x62100006abd0 <col:8> 'int' 0

Before this patch, we create a local temporary variable for the
MaterializeTemporaryExpr and destroy it again when destroying the
EvalEmitter we create to interpret the initializer. However, since
O::j is a reference, this reference now points to a local variable
that doesn't exist anymore.

Differential Revision: https://reviews.llvm.org/D156453
2023-10-19 14:50:17 +02:00
Timm Baeder
de9b3c5eba
[clang][Interp] Handle delegating constructors (#67823) 2023-10-16 14:11:25 +02:00
Timm Bäder
92ac46e703 [clang][Interp] Handle CXXParenListInitExprs
Differential Revision: https://reviews.llvm.org/D156047
2023-09-06 15:26:54 +02:00
Timm Bäder
5704dde307 [clang][Interp] Reject calling virtual constexpr functions in pre-c++20
Differential Revision: https://reviews.llvm.org/D157619
2023-09-05 12:21:26 +02:00
Timm Bäder
6d79f985b5 [clang][Interp] Implement zero-init of record types
Differential Revision: https://reviews.llvm.org/D154189
2023-09-05 11:20:35 +02:00
Timm Bäder
a13f036949 [clang][Interp] Check one-past-the-end pointers in GetPtrField
Rename CheckBaseDerived to something more general and call it in
GetPtrField() as well, so we don't crash later in Pointer::toAPValue().

Differential Revision: https://reviews.llvm.org/D149149
2023-09-05 11:00:40 +02:00
Timm Bäder
12a789710e [clang][Interp] BaseToDerived casts
We can implement these similarly to DerivedToBase casts. We just have to
walk the class hierarchy, sum the base offsets and subtract it from the
current base offset of the pointer.

Differential Revision: https://reviews.llvm.org/D149133
2023-09-05 10:53:54 +02:00
Timm Bäder
6dfe55569d [clang][Interp] Rework initializers
Before this patch, we had visitRecordInitializer() and
visitArrayInitializer(), which were different from the regular visit()
in that they expected a pointer on the top of the stack, which they
initialized. For example, visitArrayInitializer handled InitListExprs by
looping over the members and initializing the elements of that pointer.

However, this had a few corner cases and problems. For example, in
visitLambdaExpr() (a lambda is always of record type), it was not clear
whether we should always create a new local variable to save the lambda
to, or not. This is why https://reviews.llvm.org/D153616 changed
things around.

This patch changes the visiting functions to:

 - visit(): Always leaves a new value on the stack. If the expression
   can be mapped to a primitive type, it's just visited and the value is
   put on the stack. If it's of composite type, this function will
   create a local variable for the expression value and call
   visitInitializer(). The pointer to the local variable will stay on
   the stack.

 - visitInitializer(): Visits the given expression, assuming there is a
   pointer on top of the stack that will be initialized by it.

 - discard(): Visit the expression for side-effects, but don't leave a
   value on the stack.

It also adds an additional Initializing flag to differentiate between the initializing and non-initializing case.

Differential Revision: https://reviews.llvm.org/D156027
2023-08-20 13:33:08 +02:00
Timm Bäder
8a58f0d370 [clang][Interp] Handle global composite temporaries
We only did this for primitive temporaries.

Unfortunately, the existing Pointer::toAPValue() won't do here, since
we're expected to set an rvalue on the LifetimeExtendedTemporaryDecl.

Differential Revision: https://reviews.llvm.org/D144457
2023-08-20 11:15:17 +02:00
Timm Bäder
7d876c62a3 [clang][Interp] Add 'Invalid' opcode and use it for throw stmts
We will use this opcode for conditionally executed statements that are
invalid in a constant expression.

Differential Revision: https://reviews.llvm.org/D150364
2023-07-26 08:59:53 +02:00
Timm Bäder
e45d199768 [clang][Interp] Handle CXXTemporaryObjectExprs
This is a CXXConstructExpr, so create a local temporary variable and
initialize it.

Differential Revision: https://reviews.llvm.org/D147591
2023-07-26 07:36:26 +02:00
Timm Bäder
10020791b1 [clang][Interp] Call invalid destructors
We need to call them like any other function, so we can generate proper
diagnostics.

Differential Revision: https://reviews.llvm.org/D150040
2023-07-26 07:19:02 +02:00
Timm Bäder
8cb6e476cc [clang][Interp] Handle PtrMemOps
Differential Revision: https://reviews.llvm.org/D144164
2023-07-26 07:04:21 +02:00
Timm Bäder
c54ff51be9 [clang][Interp] Emit correct diagnostic for uninitialized reads
Differential Revision: https://reviews.llvm.org/D154758
2023-07-09 16:27:49 +02:00
Timm Bäder
0a9d2fa9ac [clang][Interp][NFC] Fix a test to actually test something
This was always meant to test the values of c2, not c.
2023-07-02 06:49:55 +02:00
Timm Bäder
976d8b40cc [clang][Interp] Virtual function calls
Add a CallVirt opcode and implement virtual function calls this way.

Differential Revision: https://reviews.llvm.org/D142630
2023-06-15 13:33:43 +02:00
Timm Bäder
4a6a4f84a7 [clang][Interp] Add a failing test case 2023-04-13 15:55:57 +02:00
Timm Bäder
25d6123854 [clang][Interp] Make sure we have a variable scope for initializers
Otherwise, we run into an assertion when trying to use the current
variable scope while creating temporaries for constructor initializers.

Differential Revision: https://reviews.llvm.org/D147534
2023-04-13 15:35:30 +02:00
Timm Bäder
92417f2d4b [clang][Interp] Record initialization via conditional operator
Differential Revision: https://reviews.llvm.org/D141497
2023-04-06 09:44:02 +02:00
Timm Bäder
58cf70b2cd [clang][Interp] Fix diagnostics for calling non-constexpr constructors
Differential Revision: https://reviews.llvm.org/D145841
2023-04-03 15:42:08 +02:00
Timm Bäder
db3dcdc08c [clang][Interp] Fix initializing base class members
For the given test case, we were trying to initialize a member of C,
which doesn't have any. Get the proper base pointer instead and
initialize the members there.

Differential Revision: https://reviews.llvm.org/D143466
2023-04-03 13:51:04 +02:00
Timm Bäder
968b4172f6 [clang][Interp] Fix derived-to-base casts for >1 levels
The GetPtrBasePop op we were using only works for direct base classes.

Differential Revision: https://reviews.llvm.org/D143480
2023-04-03 11:35:55 +02:00
Timm Bäder
cef69ce779 [clang][Interp] Fix record initialization via CallExpr subclasses
We can't just use VisitCallExpr() here, as that doesn't handle CallExpr
subclasses such as CXXMemberCallExpr.

Differential Revision: https://reviews.llvm.org/D141772
2023-03-31 13:16:49 +02:00
Timm Bäder
90d921fa1f [clang][Interp] Handle record initialization via CastExpr
Differential Revision: https://reviews.llvm.org/D140808
2023-03-02 10:08:41 +01:00
Timm Bäder
bf6c1344ec [clang][Interp] Handle defined functions without a body
This happens when explicitly defaulting a constructor, for example.

Differential Revision: https://reviews.llvm.org/D140776
2023-03-02 08:17:48 +01:00
Timm Bäder
f18b71d14f [clang][Interp] Implement remaining MaterializeTemporaryExpr bits
As well as support for CompoundLiteralExprs.

Differential Revision: https://reviews.llvm.org/D140668
2023-03-02 07:51:54 +01:00
Timm Bäder
cb703434cb [clang][Interp] Add back Run() call
We need to run the functions we compiled immediately after to check if
they can ever be a constant expression.

Differential Revision: https://reviews.llvm.org/D140724
2023-01-25 17:01:55 +01:00
Timm Bäder
6b0cd497b0 [clang][Interp] Check Field initialization after constructor call
Differential Revision: https://reviews.llvm.org/D136694
2023-01-19 09:42:22 +01:00
Timm Bäder
7c215a4571 [clang][Interp] Explicitly handle RVO Pointer
The calling convention is:

[RVO pointer]
[instance pointer]
[... args ...]

We handle the instance pointer ourselves, BUT for the RVO pointer, we
just assumed in visitReturnStmt() that it is on top of the stack. Which
isn't true if there are other args present (and a this pointer, maybe).

Fix this by recording the RVO pointer explicitly when creating an
InterpFrame, just like we do with the instance/This pointer.

There is already a "RVOAndParams()" test in test/AST/Inter/records.cpp,
that was supposed to test this, however, it didn't trigger any
problematic behavior because the parameter and the return value have the
same type.

Differential Revision: https://reviews.llvm.org/D137392
2022-11-30 10:37:57 +01:00
Timm Bäder
afa60d08a2 [clang][Interp] Fix discarding non-primitive function call return values
Differential Revision: https://reviews.llvm.org/D136457
2022-11-30 09:18:28 +01:00
Timm Bäder
99d3ead44c [clang][Interp] Protect Record creation against infinite recursion
This happens only in error cases, but we need to handle it anyway.

Differential Revision: https://reviews.llvm.org/D136831
2022-11-11 08:38:06 +01:00
Timm Bäder
7863646fd2 [clang][Interp] DerivedToBase casts
Differential Revision: https://reviews.llvm.org/D137545
2022-11-11 08:38:06 +01:00
Timm Bäder
38ffc89c87 [clang][Interp] Fix ignoring expression return values
Randomly noticed this. We need to honor DiscardResult here.

Differential Revision: https://reviews.llvm.org/D136013
2022-10-28 16:45:38 +02:00
Timm Bäder
f007c99ed1 [clang][Interp] Fix InterpFrame::describe() for This pointers
Since we pass this via the stack, we need to account for it when
desribing the stack frame (parameters). This fixes a previously
commented-out test case.

Differential Revision: https://reviews.llvm.org/D136670
2022-10-26 08:48:55 +02:00
Timm Bäder
cc79ddb52c [clang][Interp] Check instance pointers before calling functions on them
Remove the double Call() implementation to reduce code duplication. Then
fix Function::getSource() so we can diagnose instance pointers being
null.

Differential Revision: https://reviews.llvm.org/D135513
2022-10-22 10:32:05 +02:00