[clang] [Clang][Interp] Fix display of syntactically-invalid note for member function calls (PR #102170)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 8 10:04:50 PDT 2024
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/102170
>From 9665cf5b791b89ca9f1f80e408135f052b808b31 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Wed, 7 Aug 2024 22:15:31 +0800
Subject: [PATCH 1/3] [Clang][Interp] Fix display of syntactically-invalid note
for member function calls
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/lib/AST/Interp/Compiler.cpp | 19 ++++++------
clang/lib/AST/Interp/Context.cpp | 2 +-
clang/lib/AST/Interp/EvalEmitter.cpp | 4 +--
clang/lib/AST/Interp/Interp.cpp | 2 +-
clang/lib/AST/Interp/Interp.h | 19 ++++++------
clang/lib/AST/Interp/InterpFrame.cpp | 31 +++++++++++++------
clang/lib/AST/Interp/InterpFrame.h | 6 ++--
clang/lib/AST/Interp/Opcodes.td | 6 ++--
clang/test/AST/Interp/constexpr-nqueens.cpp | 2 +-
clang/test/AST/Interp/lambda.cpp | 2 +-
clang/test/AST/Interp/records.cpp | 4 +--
.../test/SemaCXX/constexpr-frame-describe.cpp | 5 +++
12 files changed, 62 insertions(+), 40 deletions(-)
diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index 02cbe38f5fb1fa..d0494a5065f5dc 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -2551,10 +2551,10 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
VarArgSize +=
align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));
}
- if (!this->emitCallVar(Func, VarArgSize, E))
+ if (!this->emitCallVar(Func, VarArgSize, E, E))
return false;
} else {
- if (!this->emitCall(Func, 0, E))
+ if (!this->emitCall(Func, /*VarArgSize=*/0, E, E))
return false;
}
@@ -2588,7 +2588,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return false;
}
- if (!this->emitCall(Func, 0, E))
+ if (!this->emitCall(Func, /*VarArgSize=*/0, E, E))
return false;
}
return true;
@@ -2799,7 +2799,7 @@ bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
Offset += align(primSize(PT));
}
- return this->emitCall(F, 0, E);
+ return this->emitCall(F, /*VarArgSize=*/0, E, E);
}
template <class Emitter>
@@ -4087,7 +4087,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
- if (!this->emitCallVirt(Func, VarArgSize, E))
+ if (!this->emitCallVirt(Func, VarArgSize, E, E))
return false;
} else if (Func->isVariadic()) {
uint32_t VarArgSize = 0;
@@ -4095,10 +4095,10 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
- if (!this->emitCallVar(Func, VarArgSize, E))
+ if (!this->emitCallVar(Func, VarArgSize, E, E))
return false;
} else {
- if (!this->emitCall(Func, 0, E))
+ if (!this->emitCall(Func, /*VarArgSize=*/0, E, E))
return false;
}
} else {
@@ -4705,7 +4705,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
return false;
}
- if (!this->emitCall(Func, 0, LambdaCallOp))
+ if (!this->emitCall(Func, /*VarArgSize=*/0, /*CE=*/nullptr, LambdaCallOp))
return false;
this->emitCleanup();
@@ -5567,7 +5567,8 @@ bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
assert(DtorFunc->getNumParams() == 1);
if (!this->emitDupPtr(SourceInfo{}))
return false;
- if (!this->emitCall(DtorFunc, 0, SourceInfo{}))
+ if (!this->emitCall(DtorFunc, /*VarArgSize=*/0, /*CE=*/nullptr,
+ SourceInfo{}))
return false;
}
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 92ac28137fdb45..6ea61bdc445539 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -206,7 +206,7 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
{
InterpState State(Parent, *P, Stk, *this);
State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(),
- Func->getArgSize());
+ Func->getArgSize(), /*CE=*/nullptr);
if (Interpret(State, Result)) {
assert(Stk.empty());
return true;
diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index 08536536ac3c2e..d7e442f37e23f9 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -20,8 +20,8 @@ EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
InterpStack &Stk)
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx) {
// Create a dummy frame for the interpreter which does not have locals.
- S.Current =
- new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr, CodePtr(), 0);
+ S.Current = new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr,
+ CodePtr(), /*ArgSize=*/0, /*CE=*/nullptr);
}
EvalEmitter::~EvalEmitter() {
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 0f72b860ddad77..fe38cfb54fb34c 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -872,7 +872,7 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
return false;
S.Stk.push<Pointer>(BasePtr);
- if (!Call(S, OpPC, DtorFunc, 0))
+ if (!Call(S, OpPC, DtorFunc, /*VarArgSize=*/0, /*CE=*/nullptr))
return false;
}
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 2eed0d3d1f16b3..bfe1c24288924a 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2513,7 +2513,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
}
inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
- uint32_t VarArgSize) {
+ uint32_t VarArgSize, const Expr *CE) {
if (Func->hasThisPointer()) {
size_t ArgSize = Func->getArgSize() + VarArgSize;
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
@@ -2540,7 +2540,7 @@ inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
if (!CheckCallDepth(S, OpPC))
return false;
- auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
+ auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize, CE);
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
@@ -2563,7 +2563,7 @@ inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
}
inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
- uint32_t VarArgSize) {
+ uint32_t VarArgSize, const Expr *CE) {
if (Func->hasThisPointer()) {
size_t ArgSize = Func->getArgSize() + VarArgSize;
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
@@ -2591,7 +2591,7 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
if (!CheckCallDepth(S, OpPC))
return false;
- auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
+ auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize, CE);
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
@@ -2612,7 +2612,7 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
}
inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
- uint32_t VarArgSize) {
+ uint32_t VarArgSize, const Expr *CE) {
assert(Func->hasThisPointer());
assert(Func->isVirtual());
size_t ArgSize = Func->getArgSize() + VarArgSize;
@@ -2659,7 +2659,7 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
}
}
- if (!Call(S, OpPC, Func, VarArgSize))
+ if (!Call(S, OpPC, Func, VarArgSize, CE))
return false;
// Covariant return types. The return type of Overrider is a pointer
@@ -2686,7 +2686,8 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
const CallExpr *CE) {
- auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
+ auto NewFrame =
+ std::make_unique<InterpFrame>(S, Func, PC, /*VarArgSize=*/0, CE);
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
@@ -2737,9 +2738,9 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
VarArgSize -= align(primSize(PT_Ptr));
if (F->isVirtual())
- return CallVirt(S, OpPC, F, VarArgSize);
+ return CallVirt(S, OpPC, F, VarArgSize, CE);
- return Call(S, OpPC, F, VarArgSize);
+ return Call(S, OpPC, F, VarArgSize, CE);
}
inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp
index 83784db91f4f3e..1d285dfb5f6210 100644
--- a/clang/lib/AST/Interp/InterpFrame.cpp
+++ b/clang/lib/AST/Interp/InterpFrame.cpp
@@ -18,15 +18,17 @@
#include "Program.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
using namespace clang;
using namespace clang::interp;
InterpFrame::InterpFrame(InterpState &S, const Function *Func,
- InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize)
+ InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize,
+ const clang::Expr *CE)
: Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func),
- RetPC(RetPC), ArgSize(ArgSize), Args(static_cast<char *>(S.Stk.top())),
- FrameOffset(S.Stk.size()) {
+ CallExpr(CE), RetPC(RetPC), ArgSize(ArgSize),
+ Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) {
if (!Func)
return;
@@ -46,8 +48,9 @@ InterpFrame::InterpFrame(InterpState &S, const Function *Func,
}
InterpFrame::InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
- unsigned VarArgSize)
- : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize) {
+ unsigned VarArgSize, const clang::Expr *CE)
+ : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize,
+ CE) {
// As per our calling convention, the this pointer is
// part of the ArgSize.
// If the function has RVO, the RVO pointer is first.
@@ -170,10 +173,20 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
return;
const FunctionDecl *F = getCallee();
- if (const auto *M = dyn_cast<CXXMethodDecl>(F);
- M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
- print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
- OS << "->";
+ if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
+ const Expr *Object = MCE->getImplicitObjectArgument();
+ Object->printPretty(OS, /*Helper=*/nullptr, S.getCtx().getPrintingPolicy(),
+ /*Indentation=*/0);
+ if (Object->getType()->isPointerType())
+ OS << "->";
+ else
+ OS << ".";
+ } else if (const auto *OCE =
+ dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
+ OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
+ S.getCtx().getPrintingPolicy(),
+ /*Indentation=*/0);
+ OS << ".";
}
F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(),
diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/Interp/InterpFrame.h
index 91b9b41b5d3343..6f68275faa3a97 100644
--- a/clang/lib/AST/Interp/InterpFrame.h
+++ b/clang/lib/AST/Interp/InterpFrame.h
@@ -30,14 +30,14 @@ class InterpFrame final : public Frame {
/// Creates a new frame for a method call.
InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,
- CodePtr RetPC, unsigned ArgSize);
+ CodePtr RetPC, unsigned ArgSize, const Expr *CE);
/// Creates a new frame with the values that make sense.
/// I.e., the caller is the current frame of S,
/// the This() pointer is the current Pointer on the top of S's stack,
/// and the RVO pointer is before that.
InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
- unsigned VarArgSize = 0);
+ unsigned VarArgSize = 0, const Expr *CE = nullptr);
/// Destroys the frame, killing all live pointers to stack slots.
~InterpFrame();
@@ -152,6 +152,8 @@ class InterpFrame final : public Frame {
unsigned Depth;
/// Reference to the function being executed.
const Function *Func;
+ /// The syntactical structure of member function calls
+ const Expr *CallExpr;
/// Current object pointer for methods.
Pointer This;
/// Pointer the non-primitive return value gets constructed in.
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 220dff0c556b18..9aabd9198f129e 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -198,11 +198,11 @@ def NoRet : Opcode {}
def Call : Opcode {
- let Args = [ArgFunction, ArgUint32];
+ let Args = [ArgFunction, ArgUint32, ArgExpr];
}
def CallVirt : Opcode {
- let Args = [ArgFunction, ArgUint32];
+ let Args = [ArgFunction, ArgUint32, ArgExpr];
}
def CallBI : Opcode {
@@ -214,7 +214,7 @@ def CallPtr : Opcode {
}
def CallVar : Opcode {
- let Args = [ArgFunction, ArgUint32];
+ let Args = [ArgFunction, ArgUint32, ArgExpr];
}
def OffsetOf : Opcode {
diff --git a/clang/test/AST/Interp/constexpr-nqueens.cpp b/clang/test/AST/Interp/constexpr-nqueens.cpp
index 971f99a032b665..ed038dbc9b0779 100644
--- a/clang/test/AST/Interp/constexpr-nqueens.cpp
+++ b/clang/test/AST/Interp/constexpr-nqueens.cpp
@@ -49,7 +49,7 @@ constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) {
return Row == N ? Board(0, true) :
B.ok(Row, Col) ?
tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), // ref-note {{in call to 'B.addQueen(0, 0)}} \
- // expected-note {{in call to '&Board()->addQueen(0, 0)}}
+ // expected-note {{in call to 'B.addQueen(0, 0)}}
N, Col, Row+1, B) :
buildBoardScan(N, Col, Row + 1, B);
}
diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/Interp/lambda.cpp
index d68fe995e8fa1c..27bbebddf44804 100644
--- a/clang/test/AST/Interp/lambda.cpp
+++ b/clang/test/AST/Interp/lambda.cpp
@@ -46,7 +46,7 @@ constexpr int div(int a, int b) {
return a / b; // both-note {{division by zero}}
};
- return f(); // expected-note {{in call to '&f->operator()()'}} \
+ return f(); // expected-note {{in call to 'f.operator()()'}} \
// ref-note {{in call to 'f.operator()()'}}
}
static_assert(div(8, 2) == 4);
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 479c0487fecae0..0735d4765a22aa 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -335,7 +335,7 @@ namespace InitializerTemporaries {
constexpr int f() {
S{}; // ref-note {{in call to 'S{}.~S()'}} \
- // expected-note {{in call to '&S{}->~S()'}}
+ // expected-note {{in call to '~S()'}}
return 12;
}
static_assert(f() == 12); // both-error {{not an integral constant expression}} \
@@ -599,7 +599,7 @@ namespace Destructors {
};
constexpr int testS() {
S{}; // ref-note {{in call to 'S{}.~S()'}} \
- // expected-note {{in call to '&S{}->~S()'}}
+ // expected-note {{in call to '~S()'}}
return 1;
}
static_assert(testS() == 1); // both-error {{not an integral constant expression}} \
diff --git a/clang/test/SemaCXX/constexpr-frame-describe.cpp b/clang/test/SemaCXX/constexpr-frame-describe.cpp
index 7b832d9a4b4a18..b305c281f92e5d 100644
--- a/clang/test/SemaCXX/constexpr-frame-describe.cpp
+++ b/clang/test/SemaCXX/constexpr-frame-describe.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DNEW_CONST_INTERP -std=c++20 -fexperimental-new-constant-interpreter -fsyntax-only -verify %s
struct Foo {
@@ -67,9 +68,11 @@ struct Bar {
template <typename U, int num>
constexpr int fail2() const { return 1 / 0; } // expected-warning {{division by zero}} \
// expected-note {{division by zero}}
+#ifndef NEW_CONST_INTERP
template <typename ...Args>
constexpr int fail3(Args... args) const { return 1 / 0; } // expected-warning {{division by zero}} \
// expected-note {{division by zero}}
+#endif
};
constexpr Bar<int> bar;
@@ -77,5 +80,7 @@ static_assert(bar.fail1<int>()); // expected-error {{constant expression}} \
// expected-note {{in call to 'bar.fail1<int>()'}}
static_assert(bar.fail2<int*, 42>()); // expected-error {{constant expression}} \
// expected-note {{in call to 'bar.fail2<int *, 42>()'}}
+#ifndef NEW_CONST_INTERP
static_assert(bar.fail3(3, 4UL, bar, &bar)); // expected-error {{constant expression}} \
// expected-note {{in call to 'bar.fail3<int, unsigned long, Bar<int>, const Bar<int> *>(3, 4, {}, &bar)'}}
+#endif
>From e3ff46d44c4b7dd52a5aeda2f6901af597ad2089 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 9 Aug 2024 00:45:31 +0800
Subject: [PATCH 2/3] [Clang] Fix the description of dtor and split test into
clang/test/AST/Interp
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/lib/AST/Interp/InterpFrame.cpp | 36 +++++---
.../AST/Interp/constexpr-frame-describe.cpp | 87 +++++++++++++++++++
clang/test/AST/Interp/records.cpp | 4 +-
.../test/SemaCXX/constexpr-frame-describe.cpp | 5 --
4 files changed, 112 insertions(+), 20 deletions(-)
create mode 100644 clang/test/AST/Interp/constexpr-frame-describe.cpp
diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp
index 1d285dfb5f6210..e9a930e76feeb5 100644
--- a/clang/lib/AST/Interp/InterpFrame.cpp
+++ b/clang/lib/AST/Interp/InterpFrame.cpp
@@ -173,20 +173,30 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
return;
const FunctionDecl *F = getCallee();
- if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
- const Expr *Object = MCE->getImplicitObjectArgument();
- Object->printPretty(OS, /*Helper=*/nullptr, S.getCtx().getPrintingPolicy(),
- /*Indentation=*/0);
- if (Object->getType()->isPointerType())
- OS << "->";
- else
+ bool IsMemberCall = isa<CXXMethodDecl>(F) && !isa<CXXConstructorDecl>(F) &&
+ cast<CXXMethodDecl>(F)->isImplicitObjectMemberFunction();
+ if (getThis().isActive() && IsMemberCall) {
+ if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
+ const Expr *Object = MCE->getImplicitObjectArgument();
+ Object->printPretty(OS, /*Helper=*/nullptr,
+ S.getCtx().getPrintingPolicy(),
+ /*Indentation=*/0);
+ if (Object->getType()->isPointerType())
+ OS << "->";
+ else
+ OS << ".";
+ } else if (const auto *OCE =
+ dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
+ OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
+ S.getCtx().getPrintingPolicy(),
+ /*Indentation=*/0);
OS << ".";
- } else if (const auto *OCE =
- dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
- OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
- S.getCtx().getPrintingPolicy(),
- /*Indentation=*/0);
- OS << ".";
+ } else if (const auto *M = dyn_cast<CXXMethodDecl>(F)) {
+ print(OS, This, S.getCtx(),
+ S.getCtx().getLValueReferenceType(
+ S.getCtx().getRecordType(M->getParent())));
+ OS << ".";
+ }
}
F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(),
diff --git a/clang/test/AST/Interp/constexpr-frame-describe.cpp b/clang/test/AST/Interp/constexpr-frame-describe.cpp
new file mode 100644
index 00000000000000..8c34f943d50073
--- /dev/null
+++ b/clang/test/AST/Interp/constexpr-frame-describe.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -DNEW_CONST_INTERP -std=c++20 -fexperimental-new-constant-interpreter -fsyntax-only -verify %s
+
+
+struct Foo {
+ constexpr void zomg() const { (void)(1 / 0); } // expected-error {{constant expression}} \
+ expected-warning {{division by zero}} \
+ expected-note 2{{division by zero}}
+};
+
+struct S {
+ constexpr S() {}
+ constexpr bool operator==(const S&) const { // expected-error {{never produces a constant expression}}
+ return 1 / 0; // expected-warning {{division by zero}} \
+ expected-note 3{{division by zero}}
+ }
+
+ constexpr bool heh() const {
+ auto F = new Foo();
+ F->zomg(); // expected-note {{in call to 'F->zomg()'}}
+ delete F;
+ return false;
+ }
+};
+
+constexpr S s;
+
+static_assert(s.heh()); // expected-error {{constant expression}} \
+ expected-note {{in call to 's.heh()'}}
+
+constexpr S s2;
+constexpr const S *sptr = &s;
+constexpr const S *sptr2 = &s2;
+static_assert(s == s2); // expected-error {{constant expression}} \
+ expected-note {{in call to 's.operator==(s2)'}}
+static_assert(*sptr == *sptr2); // expected-error {{constant expression}} \
+ expected-note {{in call to '*sptr.operator==(s2)'}}
+
+struct A {
+ constexpr int foo() { (void)(1/0); return 1;} // expected-error {{never produces a constant expression}} \
+ expected-warning {{division by zero}} \
+ expected-note 2{{division by zero}}
+};
+
+struct B {
+ A aa;
+ A *a = &aa;
+};
+
+struct C {
+ B b;
+};
+
+struct D {
+ C cc;
+ C *c = &cc;
+};
+
+constexpr D d{};
+static_assert(d.c->b.a->foo() == 1); // expected-error {{constant expression}} \
+ expected-note {{in call to 'd.c->b.a->foo()'}}
+
+template <typename T>
+struct Bar {
+ template <typename U>
+ constexpr int fail1() const { return 1 / 0; } // expected-warning {{division by zero}} \
+ // expected-note {{division by zero}}
+ template <typename U, int num>
+ constexpr int fail2() const { return 1 / 0; } // expected-warning {{division by zero}} \
+ // expected-note {{division by zero}}
+ template <typename ...Args>
+ constexpr int fail3(Args... args) const { return 1 / 0; } // expected-warning {{division by zero}} \
+ // expected-note {{division by zero}}
+};
+
+constexpr Bar<int> bar;
+static_assert(bar.fail1<int>()); // expected-error {{constant expression}} \
+ // expected-note {{in call to 'bar.fail1<int>()'}}
+static_assert(bar.fail2<int*, 42>()); // expected-error {{constant expression}} \
+ // expected-note {{in call to 'bar.fail2<int *, 42>()'}}
+static_assert(bar.fail3(3, 4UL, bar, &bar)); // expected-error {{constant expression}} \
+ // expected-note {{in call to 'bar.fail3<int, unsigned long, Bar<int>, const Bar<int> *>(3, 4, &bar, &bar)'}}
+#if 0
+// FIXME:
+// Current interpreter's diagnostic:
+// static_assert(bar.fail3(3, 4UL, bar, &bar)); // expected-error {{constant expression}} \
+// // expected-note {{in call to 'bar.fail3<int, unsigned long, Bar<int>, const Bar<int> *>(3, 4, {}, &bar)'}}
+#endif
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 0735d4765a22aa..5c4c1a5e81bce1 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -335,7 +335,7 @@ namespace InitializerTemporaries {
constexpr int f() {
S{}; // ref-note {{in call to 'S{}.~S()'}} \
- // expected-note {{in call to '~S()'}}
+ // expected-note {{in call to 'S{}.~S()'}}
return 12;
}
static_assert(f() == 12); // both-error {{not an integral constant expression}} \
@@ -599,7 +599,7 @@ namespace Destructors {
};
constexpr int testS() {
S{}; // ref-note {{in call to 'S{}.~S()'}} \
- // expected-note {{in call to '~S()'}}
+ // expected-note {{in call to 'S{}.~S()'}}
return 1;
}
static_assert(testS() == 1); // both-error {{not an integral constant expression}} \
diff --git a/clang/test/SemaCXX/constexpr-frame-describe.cpp b/clang/test/SemaCXX/constexpr-frame-describe.cpp
index b305c281f92e5d..7b832d9a4b4a18 100644
--- a/clang/test/SemaCXX/constexpr-frame-describe.cpp
+++ b/clang/test/SemaCXX/constexpr-frame-describe.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -DNEW_CONST_INTERP -std=c++20 -fexperimental-new-constant-interpreter -fsyntax-only -verify %s
struct Foo {
@@ -68,11 +67,9 @@ struct Bar {
template <typename U, int num>
constexpr int fail2() const { return 1 / 0; } // expected-warning {{division by zero}} \
// expected-note {{division by zero}}
-#ifndef NEW_CONST_INTERP
template <typename ...Args>
constexpr int fail3(Args... args) const { return 1 / 0; } // expected-warning {{division by zero}} \
// expected-note {{division by zero}}
-#endif
};
constexpr Bar<int> bar;
@@ -80,7 +77,5 @@ static_assert(bar.fail1<int>()); // expected-error {{constant expression}} \
// expected-note {{in call to 'bar.fail1<int>()'}}
static_assert(bar.fail2<int*, 42>()); // expected-error {{constant expression}} \
// expected-note {{in call to 'bar.fail2<int *, 42>()'}}
-#ifndef NEW_CONST_INTERP
static_assert(bar.fail3(3, 4UL, bar, &bar)); // expected-error {{constant expression}} \
// expected-note {{in call to 'bar.fail3<int, unsigned long, Bar<int>, const Bar<int> *>(3, 4, {}, &bar)'}}
-#endif
>From 48226a5963d2a076c4b52b33a153432264466be6 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 9 Aug 2024 01:01:44 +0800
Subject: [PATCH 3/3] [Clang] Revert the changes in Call* opecodes
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/lib/AST/Interp/Compiler.cpp | 40 ++++++++++++++++------------
clang/lib/AST/Interp/Context.cpp | 2 +-
clang/lib/AST/Interp/EvalEmitter.cpp | 4 +--
clang/lib/AST/Interp/Interp.cpp | 9 ++++---
clang/lib/AST/Interp/Interp.h | 25 +++++++++--------
clang/lib/AST/Interp/InterpFrame.cpp | 13 +++++----
clang/lib/AST/Interp/InterpFrame.h | 6 ++---
clang/lib/AST/Interp/Opcodes.td | 6 ++---
clang/lib/AST/Interp/Source.cpp | 2 +-
9 files changed, 55 insertions(+), 52 deletions(-)
diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index d0494a5065f5dc..11fe2acf2d7b95 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -480,19 +480,25 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
}
+ auto maybeNegate = [&]() -> bool {
+ if (CE->getCastKind() == CK_BooleanToSignedIntegral)
+ return this->emitNeg(*ToT, CE);
+ return true;
+ };
+
if (ToT == PT_IntAP)
- return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE);
+ return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE) &&
+ maybeNegate();
if (ToT == PT_IntAPS)
- return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE);
+ return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE) &&
+ maybeNegate();
if (FromT == ToT)
return true;
if (!this->emitCast(*FromT, *ToT, CE))
return false;
- if (CE->getCastKind() == CK_BooleanToSignedIntegral)
- return this->emitNeg(*ToT, CE);
- return true;
+ return maybeNegate();
}
case CK_PointerToBoolean:
@@ -2551,10 +2557,10 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
VarArgSize +=
align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));
}
- if (!this->emitCallVar(Func, VarArgSize, E, E))
+ if (!this->emitCallVar(Func, VarArgSize, E))
return false;
} else {
- if (!this->emitCall(Func, /*VarArgSize=*/0, E, E))
+ if (!this->emitCall(Func, 0, E))
return false;
}
@@ -2588,7 +2594,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return false;
}
- if (!this->emitCall(Func, /*VarArgSize=*/0, E, E))
+ if (!this->emitCall(Func, 0, E))
return false;
}
return true;
@@ -2799,7 +2805,7 @@ bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
Offset += align(primSize(PT));
}
- return this->emitCall(F, /*VarArgSize=*/0, E, E);
+ return this->emitCall(F, 0, E);
}
template <class Emitter>
@@ -3161,10 +3167,11 @@ bool Compiler<Emitter>::VisitExtVectorElementExpr(
template <class Emitter>
bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
+ const Expr *SubExpr = E->getSubExpr();
if (!E->isExpressibleAsConstantInitializer())
- return this->emitInvalid(E);
+ return this->discard(SubExpr) && this->emitInvalid(E);
- return this->delegate(E->getSubExpr());
+ return this->delegate(SubExpr);
}
template <class Emitter>
@@ -4087,7 +4094,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
- if (!this->emitCallVirt(Func, VarArgSize, E, E))
+ if (!this->emitCallVirt(Func, VarArgSize, E))
return false;
} else if (Func->isVariadic()) {
uint32_t VarArgSize = 0;
@@ -4095,10 +4102,10 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
- if (!this->emitCallVar(Func, VarArgSize, E, E))
+ if (!this->emitCallVar(Func, VarArgSize, E))
return false;
} else {
- if (!this->emitCall(Func, /*VarArgSize=*/0, E, E))
+ if (!this->emitCall(Func, 0, E))
return false;
}
} else {
@@ -4705,7 +4712,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
return false;
}
- if (!this->emitCall(Func, /*VarArgSize=*/0, /*CE=*/nullptr, LambdaCallOp))
+ if (!this->emitCall(Func, 0, LambdaCallOp))
return false;
this->emitCleanup();
@@ -5567,8 +5574,7 @@ bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
assert(DtorFunc->getNumParams() == 1);
if (!this->emitDupPtr(SourceInfo{}))
return false;
- if (!this->emitCall(DtorFunc, /*VarArgSize=*/0, /*CE=*/nullptr,
- SourceInfo{}))
+ if (!this->emitCall(DtorFunc, 0, SourceInfo{}))
return false;
}
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 6ea61bdc445539..92ac28137fdb45 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -206,7 +206,7 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
{
InterpState State(Parent, *P, Stk, *this);
State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(),
- Func->getArgSize(), /*CE=*/nullptr);
+ Func->getArgSize());
if (Interpret(State, Result)) {
assert(Stk.empty());
return true;
diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index d7e442f37e23f9..08536536ac3c2e 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -20,8 +20,8 @@ EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
InterpStack &Stk)
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx) {
// Create a dummy frame for the interpreter which does not have locals.
- S.Current = new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr,
- CodePtr(), /*ArgSize=*/0, /*CE=*/nullptr);
+ S.Current =
+ new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr, CodePtr(), 0);
}
EvalEmitter::~EvalEmitter() {
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index fe38cfb54fb34c..85cb8ff2db974e 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -301,10 +301,11 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
assert(Desc);
auto IsConstType = [&S](const VarDecl *VD) -> bool {
- if (VD->isConstexpr())
+ QualType T = VD->getType();
+
+ if (T.isConstant(S.getCtx()))
return true;
- QualType T = VD->getType();
if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
return (T->isSignedIntegerOrEnumerationType() ||
T->isUnsignedIntegerOrEnumerationType()) &&
@@ -325,7 +326,7 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
if (const auto *D = Desc->asVarDecl();
D && D->hasGlobalStorage() && D != S.EvaluatingDecl && !IsConstType(D)) {
diagnoseNonConstVariable(S, OpPC, D);
- return S.inConstantContext();
+ return false;
}
return true;
@@ -872,7 +873,7 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
return false;
S.Stk.push<Pointer>(BasePtr);
- if (!Call(S, OpPC, DtorFunc, /*VarArgSize=*/0, /*CE=*/nullptr))
+ if (!Call(S, OpPC, DtorFunc, 0))
return false;
}
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index bfe1c24288924a..832fc028ad6696 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2421,7 +2421,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
- if (!Ptr.isZero()) {
+ if (!Ptr.isZero() && !Offset.isZero()) {
if (!CheckArray(S, OpPC, Ptr))
return false;
}
@@ -2437,7 +2437,7 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
- if (!Ptr.isZero()) {
+ if (!Ptr.isZero() && !Offset.isZero()) {
if (!CheckArray(S, OpPC, Ptr))
return false;
}
@@ -2513,7 +2513,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
}
inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
- uint32_t VarArgSize, const Expr *CE) {
+ uint32_t VarArgSize) {
if (Func->hasThisPointer()) {
size_t ArgSize = Func->getArgSize() + VarArgSize;
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
@@ -2540,7 +2540,7 @@ inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
if (!CheckCallDepth(S, OpPC))
return false;
- auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize, CE);
+ auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
@@ -2563,7 +2563,7 @@ inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
}
inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
- uint32_t VarArgSize, const Expr *CE) {
+ uint32_t VarArgSize) {
if (Func->hasThisPointer()) {
size_t ArgSize = Func->getArgSize() + VarArgSize;
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
@@ -2591,7 +2591,7 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
if (!CheckCallDepth(S, OpPC))
return false;
- auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize, CE);
+ auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
@@ -2612,7 +2612,7 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
}
inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
- uint32_t VarArgSize, const Expr *CE) {
+ uint32_t VarArgSize) {
assert(Func->hasThisPointer());
assert(Func->isVirtual());
size_t ArgSize = Func->getArgSize() + VarArgSize;
@@ -2659,7 +2659,7 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
}
}
- if (!Call(S, OpPC, Func, VarArgSize, CE))
+ if (!Call(S, OpPC, Func, VarArgSize))
return false;
// Covariant return types. The return type of Overrider is a pointer
@@ -2686,8 +2686,7 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
const CallExpr *CE) {
- auto NewFrame =
- std::make_unique<InterpFrame>(S, Func, PC, /*VarArgSize=*/0, CE);
+ auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
@@ -2713,7 +2712,7 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
}
if (!FuncPtr.isValid())
- return false;
+ return Invalid(S, OpPC);
assert(F);
@@ -2738,9 +2737,9 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
VarArgSize -= align(primSize(PT_Ptr));
if (F->isVirtual())
- return CallVirt(S, OpPC, F, VarArgSize, CE);
+ return CallVirt(S, OpPC, F, VarArgSize);
- return Call(S, OpPC, F, VarArgSize, CE);
+ return Call(S, OpPC, F, VarArgSize);
}
inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp
index e9a930e76feeb5..28ffd21334b4d9 100644
--- a/clang/lib/AST/Interp/InterpFrame.cpp
+++ b/clang/lib/AST/Interp/InterpFrame.cpp
@@ -24,11 +24,10 @@ using namespace clang;
using namespace clang::interp;
InterpFrame::InterpFrame(InterpState &S, const Function *Func,
- InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize,
- const clang::Expr *CE)
+ InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize)
: Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func),
- CallExpr(CE), RetPC(RetPC), ArgSize(ArgSize),
- Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) {
+ RetPC(RetPC), ArgSize(ArgSize), Args(static_cast<char *>(S.Stk.top())),
+ FrameOffset(S.Stk.size()) {
if (!Func)
return;
@@ -48,9 +47,8 @@ InterpFrame::InterpFrame(InterpState &S, const Function *Func,
}
InterpFrame::InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
- unsigned VarArgSize, const clang::Expr *CE)
- : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize,
- CE) {
+ unsigned VarArgSize)
+ : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize) {
// As per our calling convention, the this pointer is
// part of the ArgSize.
// If the function has RVO, the RVO pointer is first.
@@ -172,6 +170,7 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
F && (F->isBuiltin() || F->isLambdaStaticInvoker()))
return;
+ const Expr *CallExpr = Caller->getExpr(getRetPC());
const FunctionDecl *F = getCallee();
bool IsMemberCall = isa<CXXMethodDecl>(F) && !isa<CXXConstructorDecl>(F) &&
cast<CXXMethodDecl>(F)->isImplicitObjectMemberFunction();
diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/Interp/InterpFrame.h
index 6f68275faa3a97..91b9b41b5d3343 100644
--- a/clang/lib/AST/Interp/InterpFrame.h
+++ b/clang/lib/AST/Interp/InterpFrame.h
@@ -30,14 +30,14 @@ class InterpFrame final : public Frame {
/// Creates a new frame for a method call.
InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,
- CodePtr RetPC, unsigned ArgSize, const Expr *CE);
+ CodePtr RetPC, unsigned ArgSize);
/// Creates a new frame with the values that make sense.
/// I.e., the caller is the current frame of S,
/// the This() pointer is the current Pointer on the top of S's stack,
/// and the RVO pointer is before that.
InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
- unsigned VarArgSize = 0, const Expr *CE = nullptr);
+ unsigned VarArgSize = 0);
/// Destroys the frame, killing all live pointers to stack slots.
~InterpFrame();
@@ -152,8 +152,6 @@ class InterpFrame final : public Frame {
unsigned Depth;
/// Reference to the function being executed.
const Function *Func;
- /// The syntactical structure of member function calls
- const Expr *CallExpr;
/// Current object pointer for methods.
Pointer This;
/// Pointer the non-primitive return value gets constructed in.
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 9aabd9198f129e..220dff0c556b18 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -198,11 +198,11 @@ def NoRet : Opcode {}
def Call : Opcode {
- let Args = [ArgFunction, ArgUint32, ArgExpr];
+ let Args = [ArgFunction, ArgUint32];
}
def CallVirt : Opcode {
- let Args = [ArgFunction, ArgUint32, ArgExpr];
+ let Args = [ArgFunction, ArgUint32];
}
def CallBI : Opcode {
@@ -214,7 +214,7 @@ def CallPtr : Opcode {
}
def CallVar : Opcode {
- let Args = [ArgFunction, ArgUint32, ArgExpr];
+ let Args = [ArgFunction, ArgUint32];
}
def OffsetOf : Opcode {
diff --git a/clang/lib/AST/Interp/Source.cpp b/clang/lib/AST/Interp/Source.cpp
index 45cd0ad4fd4273..77796b00ca52cb 100644
--- a/clang/lib/AST/Interp/Source.cpp
+++ b/clang/lib/AST/Interp/Source.cpp
@@ -41,7 +41,7 @@ const Expr *SourceInfo::asExpr() const {
const Expr *SourceMapper::getExpr(const Function *F, CodePtr PC) const {
if (const Expr *E = getSource(F, PC).asExpr())
return E;
- llvm::report_fatal_error("missing source expression");
+ return nullptr;
}
SourceLocation SourceMapper::getLocation(const Function *F, CodePtr PC) const {
More information about the cfe-commits
mailing list