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