Skip to content

Commit 59706e6

Browse files
committed
[WIP][Clang][Interp] Fix display of syntactically-invalid note for member function calls
Signed-off-by: yronglin <[email protected]>
1 parent f9b69a3 commit 59706e6

File tree

11 files changed

+61
-40
lines changed

11 files changed

+61
-40
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,10 +2551,10 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
25512551
VarArgSize +=
25522552
align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));
25532553
}
2554-
if (!this->emitCallVar(Func, VarArgSize, E))
2554+
if (!this->emitCallVar(Func, VarArgSize, E, E))
25552555
return false;
25562556
} else {
2557-
if (!this->emitCall(Func, 0, E))
2557+
if (!this->emitCall(Func, 0, E, E))
25582558
return false;
25592559
}
25602560

@@ -2588,7 +2588,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
25882588
return false;
25892589
}
25902590

2591-
if (!this->emitCall(Func, 0, E))
2591+
if (!this->emitCall(Func, 0, E, E))
25922592
return false;
25932593
}
25942594
return true;
@@ -2799,7 +2799,7 @@ bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
27992799
Offset += align(primSize(PT));
28002800
}
28012801

2802-
return this->emitCall(F, 0, E);
2802+
return this->emitCall(F, 0, E, E);
28032803
}
28042804

28052805
template <class Emitter>
@@ -4087,18 +4087,18 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
40874087
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
40884088
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
40894089

4090-
if (!this->emitCallVirt(Func, VarArgSize, E))
4090+
if (!this->emitCallVirt(Func, VarArgSize, E, E))
40914091
return false;
40924092
} else if (Func->isVariadic()) {
40934093
uint32_t VarArgSize = 0;
40944094
unsigned NumParams =
40954095
Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);
40964096
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
40974097
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
4098-
if (!this->emitCallVar(Func, VarArgSize, E))
4098+
if (!this->emitCallVar(Func, VarArgSize, E, E))
40994099
return false;
41004100
} else {
4101-
if (!this->emitCall(Func, 0, E))
4101+
if (!this->emitCall(Func, 0, E, E))
41024102
return false;
41034103
}
41044104
} else {
@@ -4705,7 +4705,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
47054705
return false;
47064706
}
47074707

4708-
if (!this->emitCall(Func, 0, LambdaCallOp))
4708+
if (!this->emitCall(Func, 0, nullptr, LambdaCallOp))
47094709
return false;
47104710

47114711
this->emitCleanup();
@@ -5567,7 +5567,7 @@ bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
55675567
assert(DtorFunc->getNumParams() == 1);
55685568
if (!this->emitDupPtr(SourceInfo{}))
55695569
return false;
5570-
if (!this->emitCall(DtorFunc, 0, SourceInfo{}))
5570+
if (!this->emitCall(DtorFunc, 0, nullptr, SourceInfo{}))
55715571
return false;
55725572
}
55735573

clang/lib/AST/Interp/Context.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
206206
{
207207
InterpState State(Parent, *P, Stk, *this);
208208
State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(),
209-
Func->getArgSize());
209+
Func->getArgSize(), /*CE=*/nullptr);
210210
if (Interpret(State, Result)) {
211211
assert(Stk.empty());
212212
return true;

clang/lib/AST/Interp/EvalEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
2020
InterpStack &Stk)
2121
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx) {
2222
// Create a dummy frame for the interpreter which does not have locals.
23-
S.Current =
24-
new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr, CodePtr(), 0);
23+
S.Current = new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr,
24+
CodePtr(), 0, /*CE=*/nullptr);
2525
}
2626

2727
EvalEmitter::~EvalEmitter() {

clang/lib/AST/Interp/Interp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
872872
return false;
873873

874874
S.Stk.push<Pointer>(BasePtr);
875-
if (!Call(S, OpPC, DtorFunc, 0))
875+
if (!Call(S, OpPC, DtorFunc, 0, 0))
876876
return false;
877877
}
878878

clang/lib/AST/Interp/Interp.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,7 +2513,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
25132513
}
25142514

25152515
inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
2516-
uint32_t VarArgSize) {
2516+
uint32_t VarArgSize, const Expr *CE) {
25172517
if (Func->hasThisPointer()) {
25182518
size_t ArgSize = Func->getArgSize() + VarArgSize;
25192519
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
@@ -2540,7 +2540,7 @@ inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
25402540
if (!CheckCallDepth(S, OpPC))
25412541
return false;
25422542

2543-
auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
2543+
auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, CE, VarArgSize);
25442544
InterpFrame *FrameBefore = S.Current;
25452545
S.Current = NewFrame.get();
25462546

@@ -2563,7 +2563,7 @@ inline bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
25632563
}
25642564

25652565
inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
2566-
uint32_t VarArgSize) {
2566+
uint32_t VarArgSize, const Expr *CE) {
25672567
if (Func->hasThisPointer()) {
25682568
size_t ArgSize = Func->getArgSize() + VarArgSize;
25692569
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
@@ -2591,7 +2591,7 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
25912591
if (!CheckCallDepth(S, OpPC))
25922592
return false;
25932593

2594-
auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
2594+
auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, CE, VarArgSize);
25952595
InterpFrame *FrameBefore = S.Current;
25962596
S.Current = NewFrame.get();
25972597

@@ -2612,7 +2612,7 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
26122612
}
26132613

26142614
inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
2615-
uint32_t VarArgSize) {
2615+
uint32_t VarArgSize, const Expr *CE) {
26162616
assert(Func->hasThisPointer());
26172617
assert(Func->isVirtual());
26182618
size_t ArgSize = Func->getArgSize() + VarArgSize;
@@ -2659,7 +2659,7 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
26592659
}
26602660
}
26612661

2662-
if (!Call(S, OpPC, Func, VarArgSize))
2662+
if (!Call(S, OpPC, Func, VarArgSize, CE))
26632663
return false;
26642664

26652665
// Covariant return types. The return type of Overrider is a pointer
@@ -2686,7 +2686,7 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
26862686

26872687
inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
26882688
const CallExpr *CE) {
2689-
auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
2689+
auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC, CE);
26902690

26912691
InterpFrame *FrameBefore = S.Current;
26922692
S.Current = NewFrame.get();
@@ -2737,9 +2737,9 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
27372737
VarArgSize -= align(primSize(PT_Ptr));
27382738

27392739
if (F->isVirtual())
2740-
return CallVirt(S, OpPC, F, VarArgSize);
2740+
return CallVirt(S, OpPC, F, VarArgSize, CE);
27412741

2742-
return Call(S, OpPC, F, VarArgSize);
2742+
return Call(S, OpPC, F, VarArgSize, CE);
27432743
}
27442744

27452745
inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {

clang/lib/AST/Interp/InterpFrame.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@
1818
#include "Program.h"
1919
#include "clang/AST/ASTContext.h"
2020
#include "clang/AST/DeclCXX.h"
21+
#include "clang/AST/ExprCXX.h"
2122

2223
using namespace clang;
2324
using namespace clang::interp;
2425

2526
InterpFrame::InterpFrame(InterpState &S, const Function *Func,
26-
InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize)
27+
InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize,
28+
const clang::Expr *CE)
2729
: Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func),
28-
RetPC(RetPC), ArgSize(ArgSize), Args(static_cast<char *>(S.Stk.top())),
29-
FrameOffset(S.Stk.size()) {
30+
CallExpr(CE), RetPC(RetPC), ArgSize(ArgSize),
31+
Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) {
3032
if (!Func)
3133
return;
3234

@@ -46,8 +48,9 @@ InterpFrame::InterpFrame(InterpState &S, const Function *Func,
4648
}
4749

4850
InterpFrame::InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
49-
unsigned VarArgSize)
50-
: InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize) {
51+
const clang::Expr *CE, unsigned VarArgSize)
52+
: InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize,
53+
CE) {
5154
// As per our calling convention, the this pointer is
5255
// part of the ArgSize.
5356
// If the function has RVO, the RVO pointer is first.
@@ -170,10 +173,26 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
170173
return;
171174

172175
const FunctionDecl *F = getCallee();
173-
if (const auto *M = dyn_cast<CXXMethodDecl>(F);
174-
M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
175-
print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
176-
OS << "->";
176+
if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
177+
const Expr *Object = MCE->getImplicitObjectArgument();
178+
Object->printPretty(OS, /*Helper=*/nullptr, S.getCtx().getPrintingPolicy(),
179+
/*Indentation=*/0);
180+
if (Object->getType()->isPointerType())
181+
OS << "->";
182+
else
183+
OS << ".";
184+
} else if (const auto *OCE =
185+
dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
186+
OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
187+
S.getCtx().getPrintingPolicy(),
188+
/*Indentation=*/0);
189+
OS << ".";
190+
} else {
191+
if (const auto *M = dyn_cast<CXXMethodDecl>(F);
192+
M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
193+
print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
194+
OS << "->";
195+
}
177196
}
178197

179198
F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(),

clang/lib/AST/Interp/InterpFrame.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ class InterpFrame final : public Frame {
3030

3131
/// Creates a new frame for a method call.
3232
InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,
33-
CodePtr RetPC, unsigned ArgSize);
33+
CodePtr RetPC, unsigned ArgSize, const Expr *CE);
3434

3535
/// Creates a new frame with the values that make sense.
3636
/// I.e., the caller is the current frame of S,
3737
/// the This() pointer is the current Pointer on the top of S's stack,
3838
/// and the RVO pointer is before that.
3939
InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
40-
unsigned VarArgSize = 0);
40+
const Expr *CE, unsigned VarArgSize = 0);
4141

4242
/// Destroys the frame, killing all live pointers to stack slots.
4343
~InterpFrame();
@@ -152,6 +152,8 @@ class InterpFrame final : public Frame {
152152
unsigned Depth;
153153
/// Reference to the function being executed.
154154
const Function *Func;
155+
/// The syntactical structure of member function calls
156+
const Expr *CallExpr;
155157
/// Current object pointer for methods.
156158
Pointer This;
157159
/// Pointer the non-primitive return value gets constructed in.

clang/lib/AST/Interp/Opcodes.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,11 @@ def NoRet : Opcode {}
198198

199199

200200
def Call : Opcode {
201-
let Args = [ArgFunction, ArgUint32];
201+
let Args = [ArgFunction, ArgUint32, ArgExpr];
202202
}
203203

204204
def CallVirt : Opcode {
205-
let Args = [ArgFunction, ArgUint32];
205+
let Args = [ArgFunction, ArgUint32, ArgExpr];
206206
}
207207

208208
def CallBI : Opcode {
@@ -214,7 +214,7 @@ def CallPtr : Opcode {
214214
}
215215

216216
def CallVar : Opcode {
217-
let Args = [ArgFunction, ArgUint32];
217+
let Args = [ArgFunction, ArgUint32, ArgExpr];
218218
}
219219

220220
def OffsetOf : Opcode {

clang/test/AST/Interp/constexpr-nqueens.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) {
4949
return Row == N ? Board(0, true) :
5050
B.ok(Row, Col) ?
5151
tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), // ref-note {{in call to 'B.addQueen(0, 0)}} \
52-
// expected-note {{in call to '&Board()->addQueen(0, 0)}}
52+
// expected-note {{in call to 'B.addQueen(0, 0)}}
5353
N, Col, Row+1, B) :
5454
buildBoardScan(N, Col, Row + 1, B);
5555
}

clang/test/AST/Interp/lambda.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ constexpr int div(int a, int b) {
4646
return a / b; // both-note {{division by zero}}
4747
};
4848

49-
return f(); // expected-note {{in call to '&f->operator()()'}} \
49+
return f(); // expected-note {{in call to 'f.operator()()'}} \
5050
// ref-note {{in call to 'f.operator()()'}}
5151
}
5252
static_assert(div(8, 2) == 4);

clang/test/AST/Interp/records.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ namespace InitializerTemporaries {
335335

336336
constexpr int f() {
337337
S{}; // ref-note {{in call to 'S{}.~S()'}} \
338-
// expected-note {{in call to '&S{}->~S()'}}
338+
// expected-note {{in call to '~S()'}}
339339
return 12;
340340
}
341341
static_assert(f() == 12); // both-error {{not an integral constant expression}} \
@@ -599,7 +599,7 @@ namespace Destructors {
599599
};
600600
constexpr int testS() {
601601
S{}; // ref-note {{in call to 'S{}.~S()'}} \
602-
// expected-note {{in call to '&S{}->~S()'}}
602+
// expected-note {{in call to '~S()'}}
603603
return 1;
604604
}
605605
static_assert(testS() == 1); // both-error {{not an integral constant expression}} \

0 commit comments

Comments
 (0)