kadircet created this revision.
kadircet added reviewers: sammccall, ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62814

Files:
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Support/ScopedPrinter.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include <string>
 
 namespace clang {
 namespace clangd {
@@ -765,6 +766,27 @@
              {std::string("bool"), std::string("T"), std::string("false")},
          };
        }},
+      // Lambda parameter with decltype
+      {R"cpp(
+        auto lamb = [](int T, bool B) -> bool { return T && B; };
+        void foo(decltype(lamb) bar) {
+          [[ba^r]](0, false);
+        }
+        )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.LocalScope = "foo::";
+         HI.Name = "bar";
+         HI.Kind = SymbolKind::Variable;
+         HI.Definition = "decltype(lamb) bar";
+         HI.Type = "bool(int, bool)";
+         HI.ReturnType = "bool";
+         HI.Parameters = {
+             {std::string("int"), std::string("T"), llvm::None},
+             {std::string("bool"), std::string("B"), llvm::None},
+         };
+         return HI;
+       }},
       // Lambda variable
       {R"cpp(
         void foo() {
@@ -779,7 +801,12 @@
          HI.Name = "lamb";
          HI.Kind = SymbolKind::Variable;
          HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
-         HI.Type = std::string("class (lambda)");
+         HI.Type = "bool(int, bool)";
+         HI.ReturnType = "bool";
+         HI.Parameters = {
+             {std::string("int"), std::string("T"), llvm::None},
+             {std::string("bool"), std::string("B"), llvm::None},
+         };
          return HI;
        }},
       // Local variable in lambda
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -18,7 +18,9 @@
 #include "index/SymbolLocation.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
@@ -652,8 +654,32 @@
     }
   }
 
+  auto ToFunctionDecl = [](const Decl *D) -> const FunctionDecl * {
+    // Extract lambda from variables.
+    if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) {
+      // It might be declared by a decltype.
+      if (const DecltypeType *DT =
+              llvm::dyn_cast<DecltypeType>(VD->getType().getTypePtr()))
+        if (!DT->getUnderlyingType().isNull())
+          if (const auto *CD = DT->getUnderlyingType()->getAsCXXRecordDecl())
+            return CD->getLambdaCallOperator();
+
+      // Or with an initializer.
+      if (const Expr *E = VD->getInit())
+        if (const LambdaExpr *LE = llvm::dyn_cast<LambdaExpr>(E))
+          return LE->getCallOperator();
+    }
+
+    // Handle classes with call operators.
+    if (const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
+      return CRD->getLambdaCallOperator();
+
+    // Non-lambda functions.
+    return D->getAsFunction();
+  };
+
   // Fill in types and params.
-  if (const FunctionDecl *FD = D->getAsFunction()) {
+  if (const FunctionDecl *FD = ToFunctionDecl(D)) {
     HI.ReturnType.emplace();
     llvm::raw_string_ostream OS(*HI.ReturnType);
     FD->getReturnType().print(OS, Policy);
@@ -692,8 +718,6 @@
     TypeOS << ')';
     // FIXME: handle variadics.
   } else if (const auto *VD = dyn_cast<ValueDecl>(D)) {
-    // FIXME: Currently lambdas are also handled as ValueDecls, they should be
-    // more similar to functions.
     HI.Type.emplace();
     llvm::raw_string_ostream OS(*HI.Type);
     VD->getType().print(OS, Policy);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to