From 943ef06420105cad23e3caea24d6a274cdb0316f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Thu, 26 Jan 2023 14:07:46 +0100 Subject: [PATCH] [clang][Interp] Check This pointer without creating InterpFrame The InterpFrame was only created so early so we could use getThis(). However, we need to know the Function when creating the InterpFrame and in the case of virtual functions, we need to determine what function to call at interpretation time. Get the This pointer ourselves and just create the InterpFrame later. Differential Revision: https://reviews.llvm.org/D142617 --- clang/lib/AST/Interp/Interp.h | 8 +++++--- clang/lib/AST/Interp/InterpStack.cpp | 2 +- clang/lib/AST/Interp/InterpStack.h | 11 ++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index bb34737..afc5f24 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1492,10 +1492,11 @@ inline bool CheckGlobalCtor(InterpState &S, CodePtr &PC) { } inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { - auto NewFrame = std::make_unique(S, Func, PC); - Pointer ThisPtr; if (Func->hasThisPointer()) { - ThisPtr = NewFrame->getThis(); + size_t ThisOffset = + Func->getArgSize() + (Func->hasRVO() ? primSize(PT_Ptr) : 0); + const Pointer &ThisPtr = S.Stk.peek(ThisOffset); + if (!CheckInvoke(S, PC, ThisPtr)) return false; @@ -1506,6 +1507,7 @@ inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { if (!CheckCallable(S, PC, Func)) return false; + auto NewFrame = std::make_unique(S, Func, PC); InterpFrame *FrameBefore = S.Current; S.Current = NewFrame.get(); diff --git a/clang/lib/AST/Interp/InterpStack.cpp b/clang/lib/AST/Interp/InterpStack.cpp index 7fe678e..63a088b 100644 --- a/clang/lib/AST/Interp/InterpStack.cpp +++ b/clang/lib/AST/Interp/InterpStack.cpp @@ -46,7 +46,7 @@ void *InterpStack::grow(size_t Size) { return Object; } -void *InterpStack::peek(size_t Size) const { +void *InterpStack::peekData(size_t Size) const { assert(Chunk && "Stack is empty!"); StackChunk *Ptr = Chunk; diff --git a/clang/lib/AST/Interp/InterpStack.h b/clang/lib/AST/Interp/InterpStack.h index e625ffd..435120d 100644 --- a/clang/lib/AST/Interp/InterpStack.h +++ b/clang/lib/AST/Interp/InterpStack.h @@ -64,11 +64,16 @@ public: /// Returns a reference to the value on the top of the stack. template T &peek() const { - return *reinterpret_cast(peek(aligned_size())); + return *reinterpret_cast(peekData(aligned_size())); + } + + template T &peek(size_t Offset) const { + assert(aligned(Offset)); + return *reinterpret_cast(peekData(Offset)); } /// Returns a pointer to the top object. - void *top() const { return Chunk ? peek(0) : nullptr; } + void *top() const { return Chunk ? peekData(0) : nullptr; } /// Returns the size of the stack in bytes. size_t size() const { return StackSize; } @@ -90,7 +95,7 @@ private: /// Grows the stack to accommodate a value and returns a pointer to it. void *grow(size_t Size); /// Returns a pointer from the top of the stack. - void *peek(size_t Size) const; + void *peekData(size_t Size) const; /// Shrinks the stack. void shrink(size_t Size); -- 2.7.4