https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/102170

>From f14464c0734776cd79a2fbd93cec94e815276009 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin...@gmail.com>
Date: Fri, 9 Aug 2024 01:22:29 +0800
Subject: [PATCH 1/2] [Clang][Interp] Fix display of syntactically-invalid note
 for member function calls

Signed-off-by: yronglin <yronglin...@gmail.com>
---
 clang/lib/AST/Interp/InterpFrame.cpp          | 30 ++++++-
 clang/lib/AST/Interp/Source.cpp               |  2 +-
 .../AST/Interp/constexpr-frame-describe.cpp   | 83 +++++++++++++++++++
 clang/test/AST/Interp/constexpr-nqueens.cpp   |  2 +-
 clang/test/AST/Interp/lambda.cpp              |  2 +-
 clang/test/AST/Interp/records.cpp             |  6 +-
 6 files changed, 114 insertions(+), 11 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 83784db91f4f3..27108f957305f 100644
--- a/clang/lib/AST/Interp/InterpFrame.cpp
+++ b/clang/lib/AST/Interp/InterpFrame.cpp
@@ -18,6 +18,7 @@
 #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;
@@ -169,11 +170,32 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
       F && (F->isBuiltin() || F->isLambdaStaticInvoker()))
     return;
 
+  const Expr *CallExpr = Caller->getExpr(getRetPC());
   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 << "->";
+  bool IsMemberCall = isa<CXXMethodDecl>(F) && !isa<CXXConstructorDecl>(F) &&
+                      cast<CXXMethodDecl>(F)->isImplicitObjectMemberFunction();
+  if (Func->hasThisPointer() && 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 *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/lib/AST/Interp/Source.cpp b/clang/lib/AST/Interp/Source.cpp
index 45cd0ad4fd427..77796b00ca52c 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 {
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 0000000000000..fe698362e3d9b
--- /dev/null
+++ b/clang/test/AST/Interp/constexpr-frame-describe.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,both %s
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-fsyntax-only -verify=ref,both %s
+
+
+struct Foo {
+    constexpr void zomg() const { (void)(1 / 0); } // both-error {{constant 
expression}} \
+                                                      both-warning {{division 
by zero}} \
+                                                      both-note 2{{division by 
zero}}
+};
+
+struct S {
+    constexpr S() {}
+    constexpr bool operator==(const S&) const { // both-error {{never produces 
a constant expression}}
+      return 1 / 0; // both-warning {{division by zero}} \
+                       both-note 3{{division by zero}}
+    }
+
+    constexpr bool heh() const {
+        auto F = new Foo();
+        F->zomg(); // both-note {{in call to 'F->zomg()'}}
+        delete F;
+        return false;
+    }
+};
+
+constexpr S s;
+
+static_assert(s.heh()); // both-error {{constant expression}} \
+                           both-note {{in call to 's.heh()'}}
+
+constexpr S s2;
+constexpr const S *sptr = &s;
+constexpr const S *sptr2 = &s2;
+static_assert(s == s2); // both-error {{constant expression}} \
+                           both-note {{in call to 's.operator==(s2)'}}
+static_assert(*sptr == *sptr2); // both-error {{constant expression}} \
+                                   both-note {{in call to 
'*sptr.operator==(s2)'}}
+
+struct A {
+  constexpr int foo() { (void)(1/0); return 1;} // both-error {{never produces 
a constant expression}} \
+                                                   both-warning {{division by 
zero}} \
+                                                   both-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); // both-error {{constant expression}} \
+                                        both-note {{in call to 
'd.c->b.a->foo()'}}
+
+template <typename T>
+struct Bar {
+  template <typename U>
+  constexpr int fail1() const { return 1 / 0; } // both-warning {{division by 
zero}} \
+                                                // both-note {{division by 
zero}}
+  template <typename U, int num>
+  constexpr int fail2() const { return 1 / 0; } // both-warning {{division by 
zero}} \
+                                                // both-note {{division by 
zero}}
+  template <typename ...Args>
+  constexpr int fail3(Args... args) const { return 1 / 0; } // both-warning 
{{division by zero}} \
+                                                // both-note {{division by 
zero}}
+};
+
+constexpr Bar<int> bar;
+static_assert(bar.fail1<int>()); // both-error {{constant expression}} \
+                                 // both-note {{in call to 'bar.fail1<int>()'}}
+static_assert(bar.fail2<int*, 42>()); // both-error {{constant expression}} \
+                                      // both-note {{in call to 'bar.fail2<int 
*, 42>()'}}
+static_assert(bar.fail3(3, 4UL, bar, &bar)); // both-error {{constant 
expression}} \
+                                             // expected-note {{in call to 
'bar.fail3<int, unsigned long, Bar<int>, const Bar<int> *>(3, 4, &bar, &bar)'}} 
\
+                                             // ref-note {{in call to 
'bar.fail3<int, unsigned long, Bar<int>, const Bar<int> *>(3, 4, {}, &bar)'}}
diff --git a/clang/test/AST/Interp/constexpr-nqueens.cpp 
b/clang/test/AST/Interp/constexpr-nqueens.cpp
index 971f99a032b66..ed038dbc9b077 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 d68fe995e8fa1..27bbebddf4480 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 479c0487fecae..9c8c1c344e1e8 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -334,8 +334,7 @@ namespace InitializerTemporaries {
   };
 
   constexpr int f() {
-    S{}; // ref-note {{in call to 'S{}.~S()'}} \
-         // expected-note {{in call to '&S{}->~S()'}}
+    S{}; // both-note {{in call to 'S{}.~S()'}}
     return 12;
   }
   static_assert(f() == 12); // both-error {{not an integral constant 
expression}} \
@@ -598,8 +597,7 @@ namespace Destructors {
     }
   };
   constexpr int testS() {
-    S{}; // ref-note {{in call to 'S{}.~S()'}} \
-         // expected-note {{in call to '&S{}->~S()'}}
+    S{}; // both-note {{in call to 'S{}.~S()'}}
     return 1;
   }
   static_assert(testS() == 1); // both-error {{not an integral constant 
expression}} \

>From b95df20be661b0f4d0f50bf6200d2d094d515057 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin...@gmail.com>
Date: Fri, 9 Aug 2024 11:14:15 +0800
Subject: [PATCH 2/2] [Clang] Update test

Signed-off-by: yronglin <yronglin...@gmail.com>
---
 clang/test/AST/Interp/constexpr-frame-describe.cpp | 4 ++--
 clang/test/AST/Interp/lambda.cpp                   | 3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/test/AST/Interp/constexpr-frame-describe.cpp 
b/clang/test/AST/Interp/constexpr-frame-describe.cpp
index fe698362e3d9b..e039fd61ae981 100644
--- a/clang/test/AST/Interp/constexpr-frame-describe.cpp
+++ b/clang/test/AST/Interp/constexpr-frame-describe.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,both %s
-// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-fsyntax-only -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-fsyntax-only -verify=expected,both %s
 
 
 struct Foo {
diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/Interp/lambda.cpp
index 27bbebddf4480..e4390483d0053 100644
--- a/clang/test/AST/Interp/lambda.cpp
+++ b/clang/test/AST/Interp/lambda.cpp
@@ -46,8 +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()()'}} \
-              // ref-note {{in call to 'f.operator()()'}}
+  return f(); // both-note {{in call to 'f.operator()()'}}
 }
 static_assert(div(8, 2) == 4);
 static_assert(div(8, 0) == 4); // both-error {{not an integral constant 
expression}} \

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to