[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