[clang-tools-extra] [clangd] Avoid crash when summarizing pointer-to-member expr for block-end hint (PR #76492)

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 28 23:10:13 PST 2023


https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/76492

>From ec31d400915dba372501c49db8bab7c8123228df Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Thu, 28 Dec 2023 02:47:04 -0500
Subject: [PATCH] [clangd] Avoid crash when summarizing pointer-to-member expr
 for block-end hint

For calls through a pointer to member, CXXMemberCallExpr::getCallee() is
a BinaryOperator with operator ->* (after unwrapping parens).

getMethodDecl() only returns non-null if the callee is a MemberExpr.

Fixes https://github.com/clangd/clangd/issues/1873
---
 clang-tools-extra/clangd/InlayHints.cpp             |  2 +-
 .../clangd/unittests/InlayHintTests.cpp             | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp
index 3da047f9542138..fd28b48b5a0b02 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -286,7 +286,7 @@ std::string summarizeExpr(const Expr *E) {
     // Step through implicit nodes that clang doesn't classify as such.
     std::string VisitCXXMemberCallExpr(const CXXMemberCallExpr *E) {
       // Call to operator bool() inside if (X): dispatch to X.
-      if (E->getNumArgs() == 0 &&
+      if (E->getNumArgs() == 0 && E->getMethodDecl() &&
           E->getMethodDecl()->getDeclName().getNameKind() ==
               DeclarationName::CXXConversionFunctionName &&
           E->getSourceRange() ==
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 20c1cdd985dbc0..ea5ee18f1da65c 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -2172,6 +2172,19 @@ TEST(BlockEndHints, Macro) {
                       ExpectedHint{" // struct S1", "S1"});
 }
 
+TEST(BlockEndHints, PointerToMemberFunction) {
+  // Do not crash trying to summarize `a->*p`.
+  assertBlockEndHints(R"cpp(
+    class A {};
+    using Predicate = bool(A::*)();
+    void foo(A* a, Predicate p) {
+      if ((a->*p)()) {
+      $ptrmem[[}]]
+    } // suppress
+  )cpp",
+                      ExpectedHint{" // if", "ptrmem"});
+}
+
 // FIXME: Low-hanging fruit where we could omit a type hint:
 //  - auto x = TypeName(...);
 //  - auto x = (TypeName) (...);



More information about the cfe-commits mailing list