massberg created this revision.
massberg added a reviewer: sammccall.
Herald added subscribers: kadircet, arphaman, kristof.beyls.
Herald added a project: All.
massberg requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added projects: clang, clang-tools-extra.

Consider type constraints of TemplateTypeParmDecls in FindTarget.
To this end TemplateTypeParmTypeLoc:getLocalSourceRange() now also includes
the whole constraint if there is any.

In clangd this enables that Hover now works for type constraints of auto 
function parameters and
template parameters.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155460

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp
  clang/include/clang/AST/TypeLoc.h
  clang/lib/AST/TypeLoc.cpp
  clang/unittests/AST/SourceLocationTest.cpp

Index: clang/unittests/AST/SourceLocationTest.cpp
===================================================================
--- clang/unittests/AST/SourceLocationTest.cpp
+++ clang/unittests/AST/SourceLocationTest.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Testing/CommandLineArgs.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Testing/Annotations/Annotations.h"
 #include "gtest/gtest.h"
@@ -263,6 +264,19 @@
   EXPECT_TRUE(Verifier.match(Code, typeLoc(loc(autoType())), Lang_CXX20));
 }
 
+TEST(TypeLoc, TemplateTypeParmTypeLocRange) {
+  RangeVerifier<TypeLoc> Verifier;
+  Verifier.expectRange(2, 10, 2, 18);
+  EXPECT_TRUE(Verifier.match("template <typename T> concept Fooable = true;\n"
+                             "void Bar(Fooable auto x) {}",
+                             typeLoc(loc(templateTypeParmType())), Lang_CXX20));
+
+  Verifier.expectRange(2, 11, 2, 31);
+  EXPECT_TRUE(Verifier.match("template <typename T> concept Fooable = true;\n"
+                             "template <Fooable T> void bar(T t) {}",
+                             typeLoc(loc(templateTypeParmType())), Lang_CXX20));
+}
+
 TEST(TypeLoc, LongDoubleRange) {
   RangeVerifier<TypeLoc> Verifier;
   Verifier.expectRange(1, 1, 1, 6);
@@ -370,10 +384,10 @@
 TEST(CompoundLiteralExpr, ParensCompoundVectorLiteralRange) {
   RangeVerifier<CompoundLiteralExpr> Verifier;
   Verifier.expectRange(2, 20, 2, 31);
-  EXPECT_TRUE(Verifier.match(
-                  "typedef int int2 __attribute__((ext_vector_type(2)));\n"
-                  "constant int2 i2 = (int2)(1, 2);", 
-                  compoundLiteralExpr(), Lang_OpenCL));
+  EXPECT_TRUE(
+      Verifier.match("typedef int int2 __attribute__((ext_vector_type(2)));\n"
+                     "constant int2 i2 = (int2)(1, 2);",
+                     compoundLiteralExpr(), Lang_OpenCL));
 }
 
 TEST(InitListExpr, VectorLiteralListBraceRange) {
Index: clang/lib/AST/TypeLoc.cpp
===================================================================
--- clang/lib/AST/TypeLoc.cpp
+++ clang/lib/AST/TypeLoc.cpp
@@ -11,9 +11,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/TypeLoc.h"
-#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ASTConcept.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateBase.h"
@@ -718,3 +719,21 @@
     return AutoTypeLoc();
   return Res.getAs<AutoTypeLoc>();
 }
+
+SourceRange TemplateTypeParmTypeLoc::getLocalSourceRange() const {
+  SourceRange SR =
+      InheritingConcreteTypeLoc<TypeSpecTypeLoc, TemplateTypeParmTypeLoc,
+                                TemplateTypeParmType>::getLocalSourceRange();
+  SourceLocation StartLoc = SR.getBegin();
+
+  if (auto *D = getDecl()) {
+    if (auto *TC = D->getTypeConstraint()) {
+      if (TC->getNestedNameSpecifierLoc()) {
+        StartLoc = TC->getNestedNameSpecifierLoc().getBeginLoc();
+      } else {
+        StartLoc = TC->getConceptNameLoc();
+      }
+    }
+  }
+  return SourceRange(StartLoc, getNameLoc());
+}
Index: clang/include/clang/AST/TypeLoc.h
===================================================================
--- clang/include/clang/AST/TypeLoc.h
+++ clang/include/clang/AST/TypeLoc.h
@@ -751,6 +751,8 @@
                                      TemplateTypeParmType> {
 public:
   TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); }
+
+  SourceRange getLocalSourceRange() const;
 };
 
 struct ObjCTypeParamTypeLocInfo {
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -487,6 +487,29 @@
          HI.Kind = index::SymbolKind::TypeAlias;
          HI.Definition = "int";
        }},
+      // constrained function parameter
+      {R"cpp(
+        template <class T> concept Fooable = true;
+        void Foo([[Fooa^ble]] auto x) {}
+        )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "Fooable";
+         HI.Kind = index::SymbolKind::Concept;
+         HI.Definition = "template <class T>\nconcept Fooable = true";
+       }},
+      // constrained template parameter
+      {R"cpp(
+        template <class T> concept Fooable = true;
+        template <[[Foo^able]] T>
+        void bar(T t) {}
+        )cpp",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "Fooable";
+         HI.Kind = index::SymbolKind::Concept;
+         HI.Definition = "template <class T>\nconcept Fooable = true";
+       }},
       // auto on lambda
       {R"cpp(
         void foo() {
@@ -3024,58 +3047,59 @@
   struct {
     const char *Code;
     const std::function<void(HoverInfo &)> ExpectedBuilder;
-  } Cases[] = {{R"cpp(
-                  struct Foo {};                     
+  } Cases[] = {
+      {R"cpp(
+                  struct Foo {};
                   Foo F = Fo^o{};
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = ""; }},
-               {R"cpp(
-                  #include "foo.h"                   
+       [](HoverInfo &HI) { HI.Provider = ""; }},
+      {R"cpp(
+                  #include "foo.h"
                   Foo F = Fo^o{};
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
-               {R"cpp(
-                  #include "all.h"  
+       [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
+      {R"cpp(
+                  #include "all.h"
                   Foo F = Fo^o{};
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
-               {R"cpp(
+       [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
+      {R"cpp(
                   #define FOO 5
                   int F = ^FOO;
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = ""; }},
-               {R"cpp(
+       [](HoverInfo &HI) { HI.Provider = ""; }},
+      {R"cpp(
                   #include "foo.h"
                   int F = ^FOO;
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
-               {R"cpp(
+       [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
+      {R"cpp(
                   #include "all.h"
                   int F = ^FOO;
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
-               {R"cpp(
-                  #include "foo.h"    
+       [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
+      {R"cpp(
+                  #include "foo.h"
                   Foo A;
                   Foo B;
                   Foo C = A ^+ B;
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
-               // Hover selects the underlying decl of the using decl
-               {R"cpp(
+       [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
+      // Hover selects the underlying decl of the using decl
+      {R"cpp(
                   #include "foo.h"
                   namespace ns {
                     using ::Foo;
                   }
                   ns::F^oo d;
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
-                {R"cpp(
+       [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
+      {R"cpp(
                   namespace foo {};
                   using namespace fo^o;
                 )cpp",
-                [](HoverInfo &HI) { HI.Provider = ""; }},
-                };
+       [](HoverInfo &HI) { HI.Provider = ""; }},
+  };
 
   for (const auto &Case : Cases) {
     Annotations Code{Case.Code};
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -559,7 +559,7 @@
     template <[[Fooable]] T>
     void bar(T t);
   )cpp";
-  EXPECT_DECLS("ConceptSpecializationExpr",
+  EXPECT_DECLS("TemplateTypeParmTypeLoc",
                {"template <typename T> concept Fooable = true"});
 
   // partial-concept-id
@@ -570,7 +570,17 @@
     template <[[Fooable]]<int> T>
     void bar(T t);
   )cpp";
-  EXPECT_DECLS("ConceptSpecializationExpr",
+  EXPECT_DECLS("TemplateTypeParmTypeLoc",
+               {"template <typename T, typename U> concept Fooable = true"});
+
+  // Constrained function parameter
+  Code = R"cpp(
+    template <typename T, typename U>
+    concept Fooable = true;
+
+    void Foo([[Fooable]]<int> auto t);
+  )cpp";
+  EXPECT_DECLS("TemplateTypeParmTypeLoc",
                {"template <typename T, typename U> concept Fooable = true"});
 }
 
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -230,6 +230,11 @@
                    dyn_cast<ObjCCategoryImplDecl>(D)) {
       // Treat ObjC{Category,CategoryImpl}Decl as if they were a decl/def pair.
       D = CID->getCategoryDecl();
+    } else if (const TemplateTypeParmDecl *TTPD =
+                   dyn_cast<TemplateTypeParmDecl>(D)) {
+      if (auto *TC = TTPD->getTypeConstraint()) {
+        D = TC->getNamedConcept();
+      }
     }
     if (!D)
       return;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to