[clang] 75e16fd - [Index] [clangd] Support for concept declarations and requires expressions

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 26 06:50:13 PDT 2022


Author: Ilya Biryukov
Date: 2022-04-26T13:50:01Z
New Revision: 75e16fd2c656fb7d27e6edc46dc1a63ff8323999

URL: https://github.com/llvm/llvm-project/commit/75e16fd2c656fb7d27e6edc46dc1a63ff8323999
DIFF: https://github.com/llvm/llvm-project/commit/75e16fd2c656fb7d27e6edc46dc1a63ff8323999.diff

LOG: [Index] [clangd] Support for concept declarations and requires expressions

Add support for concepts and requires expression in the clang index.
Genarate USRs for concepts.

Also change how `RecursiveASTVisitor` handles return type requirement in
requires expressions. The new code unpacks the synthetic template parameter
list used for storing the actual expression. This simplifies
implementation of the indexing. No code seems to depend on the original
traversal anyway and the synthesized template parameter list is easily
accessible from inside the requires expression if needed.

Add tests in the clangd codebase.

Fixes https://github.com/clangd/clangd/issues/1103.

Reviewed By: sammccall

Differential Revision: https://reviews.llvm.org/D124441

Added: 
    

Modified: 
    clang-tools-extra/clangd/CodeComplete.cpp
    clang-tools-extra/clangd/Protocol.cpp
    clang-tools-extra/clangd/Quality.cpp
    clang-tools-extra/clangd/index/SymbolCollector.cpp
    clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
    clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
    clang-tools-extra/clangd/unittests/TestIndex.cpp
    clang-tools-extra/clangd/unittests/TestIndex.h
    clang-tools-extra/clangd/unittests/XRefsTests.cpp
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/Index/IndexSymbol.h
    clang/lib/Index/IndexBody.cpp
    clang/lib/Index/IndexDecl.cpp
    clang/lib/Index/IndexSymbol.cpp
    clang/lib/Index/IndexTypeSourceInfo.cpp
    clang/lib/Index/IndexingContext.cpp
    clang/lib/Index/USRGeneration.cpp
    clang/tools/libclang/CXIndexDataConsumer.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 53989ca6ada3b..920fb77f07dee 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -129,6 +129,8 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
   case SK::TemplateTypeParm:
   case SK::TemplateTemplateParm:
     return CompletionItemKind::TypeParameter;
+  case SK::Concept:
+    return CompletionItemKind::Interface;
   }
   llvm_unreachable("Unhandled clang::index::SymbolKind.");
 }

diff  --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 0144d16320260..7c7d1b7cf7a70 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -301,6 +301,8 @@ SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
   case index::SymbolKind::TemplateTemplateParm:
   case index::SymbolKind::TemplateTypeParm:
     return SymbolKind::TypeParameter;
+  case index::SymbolKind::Concept:
+    return SymbolKind::Interface;
   }
   llvm_unreachable("invalid symbol kind");
 }

diff  --git a/clang-tools-extra/clangd/Quality.cpp b/clang-tools-extra/clangd/Quality.cpp
index 3546d976c5b8d..0f7c2d3da1c6c 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -122,6 +122,7 @@ categorize(const index::SymbolInfo &D) {
   case index::SymbolKind::TypeAlias:
   case index::SymbolKind::TemplateTypeParm:
   case index::SymbolKind::TemplateTemplateParm:
+  case index::SymbolKind::Concept:
     return SymbolQualitySignals::Type;
   case index::SymbolKind::Function:
   case index::SymbolKind::ClassMethod:

diff  --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp
index 6153b35edcfdb..ee948f80e7a6d 100644
--- a/clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -88,6 +88,7 @@ bool shouldCollectIncludePath(index::SymbolKind Kind) {
   case SK::Function:
   case SK::Variable:
   case SK::EnumConstant:
+  case SK::Concept:
     return true;
   default:
     return false;

diff  --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index a0fcb62575e9a..2e42786f76ad6 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3565,6 +3565,38 @@ TEST(CompletionTest, CommentParamName) {
               IsEmpty());
 }
 
+TEST(CompletionTest, Concepts) {
+  Annotations Code(R"cpp(
+    template<class T>
+    concept A = sizeof(T) <= 8;
+
+    template<$tparam^A U>
+    int foo();
+
+    template<class T>
+    concept b = $other^A<T> && $other^sizeof(T) % 2 == 0 || $other^A<T> && sizeof(T) == 1;
+
+    $other^A<T> auto i = 19;
+  )cpp");
+  TestTU TU;
+  TU.Code = Code.code().str();
+  TU.ExtraArgs = {"-std=c++20"};
+
+  std::vector<Symbol> Syms = {conceptSym("same_as")};
+  for (auto P : Code.points("tparam")) {
+    ASSERT_THAT(completions(TU, P, Syms).Completions,
+                AllOf(Contains(named("A")), Contains(named("same_as")),
+                      Contains(named("class")), Contains(named("typename"))))
+        << "Completing template parameter at position " << P;
+  }
+
+  for (auto P : Code.points("other")) {
+    EXPECT_THAT(completions(TU, P, Syms).Completions,
+                AllOf(Contains(named("A")), Contains(named("same_as"))))
+        << "Completing 'requires' expression at position " << P;
+  }
+}
+
 TEST(SignatureHelp, DocFormat) {
   Annotations Code(R"cpp(
     // Comment `with` markup.

diff  --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index f8a891d12f5a0..32c889876f24c 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -59,6 +59,7 @@ MATCHER_P(hasName, Name, "") { return arg.Name == Name; }
 MATCHER_P(templateArgs, TemplArgs, "") {
   return arg.TemplateSpecializationArgs == TemplArgs;
 }
+MATCHER_P(hasKind, Kind, "") { return arg.SymInfo.Kind == Kind; }
 MATCHER_P(declURI, P, "") {
   return StringRef(arg.CanonicalDeclaration.FileURI) == P;
 }
@@ -1962,6 +1963,17 @@ TEST_F(SymbolCollectorTest, Reserved) {
   EXPECT_THAT(Symbols, IsEmpty());
 }
 
+TEST_F(SymbolCollectorTest, Concepts) {
+  const char *Header = R"cpp(
+    template <class T>
+    concept A = sizeof(T) <= 8;
+  )cpp";
+  runSymbolCollector("", Header, {"-std=c++20"});
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(AllOf(
+                  qName("A"), hasKind(clang::index::SymbolKind::Concept))));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

diff  --git a/clang-tools-extra/clangd/unittests/TestIndex.cpp b/clang-tools-extra/clangd/unittests/TestIndex.cpp
index 9bec48cdc8ebb..3378ac856fc6d 100644
--- a/clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ b/clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -77,6 +77,10 @@ Symbol ns(llvm::StringRef Name) {
   return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
 }
 
+Symbol conceptSym(llvm::StringRef Name) {
+  return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
+}
+
 SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames) {
   SymbolSlab::Builder Slab;
   for (llvm::StringRef QName : QualifiedNames)

diff  --git a/clang-tools-extra/clangd/unittests/TestIndex.h b/clang-tools-extra/clangd/unittests/TestIndex.h
index 76f88cd117acf..b55f82eac3292 100644
--- a/clang-tools-extra/clangd/unittests/TestIndex.h
+++ b/clang-tools-extra/clangd/unittests/TestIndex.h
@@ -31,6 +31,8 @@ Symbol enm(llvm::StringRef Name);
 Symbol var(llvm::StringRef Name);
 // Creates a namespace symbol.
 Symbol ns(llvm::StringRef Name);
+// Create a C++20 concept symbol.
+Symbol conceptSym(llvm::StringRef Name);
 
 // Create a slab of symbols with the given qualified names as IDs and names.
 SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames);

diff  --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index 3ecbcfd3726c0..98693a5d6e4fc 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1850,6 +1850,8 @@ TEST(FindType, All) {
 void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {
   Annotations T(Test);
   auto TU = TestTU::withCode(T.code());
+  TU.ExtraArgs.push_back("-std=c++20");
+
   auto AST = TU.build();
   std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
   for (const auto &R : T.ranges())
@@ -2064,6 +2066,38 @@ TEST(FindReferences, WithinAST) {
     checkFindRefs(Test);
 }
 
+TEST(FindReferences, ConceptsWithinAST) {
+  constexpr llvm::StringLiteral Code = R"cpp(
+    template <class T>
+    concept $def[[IsSmal^l]] = sizeof(T) <= 8;
+
+    template <class T>
+    concept IsSmallPtr = requires(T x) {
+      { *x } -> [[IsSmal^l]];
+    };
+
+    [[IsSmall]] auto i = 'c';
+    template<[[IsSmal^l]] U> void foo();
+    template<class U> void bar() requires [[IsSmal^l]]<U>;
+    template<class U> requires [[IsSmal^l]]<U> void baz();
+    static_assert([[IsSma^ll]]<char>);
+  )cpp";
+  checkFindRefs(Code);
+}
+
+TEST(FindReferences, RequiresExprParameters) {
+  constexpr llvm::StringLiteral Code = R"cpp(
+    template <class T>
+    concept IsSmall = sizeof(T) <= 8;
+
+    template <class T>
+    concept IsSmallPtr = requires(T $def[[^x]]) {
+      { *[[^x]] } -> IsSmall;
+    };
+  )cpp";
+  checkFindRefs(Code);
+}
+
 TEST(FindReferences, IncludeOverrides) {
   llvm::StringRef Test =
       R"cpp(

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 0fef6982930e4..f143df5c3c17f 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2841,9 +2841,10 @@ DEF_TRAVERSE_STMT(RequiresExpr, {
       if (!ExprReq->isExprSubstitutionFailure())
         TRY_TO(TraverseStmt(ExprReq->getExpr()));
       auto &RetReq = ExprReq->getReturnTypeRequirement();
-      if (RetReq.isTypeConstraint())
-        TRY_TO(TraverseTemplateParameterListHelper(
-                   RetReq.getTypeConstraintTemplateParameterList()));
+      if (RetReq.isTypeConstraint()) {
+        TRY_TO(TraverseStmt(
+            RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint()));
+      }
     } else {
       auto *NestedReq = cast<concepts::NestedRequirement>(Req);
       if (!NestedReq->isSubstitutionFailure())

diff  --git a/clang/include/clang/Index/IndexSymbol.h b/clang/include/clang/Index/IndexSymbol.h
index 2ba81986c2fe2..59e90fced3dda 100644
--- a/clang/include/clang/Index/IndexSymbol.h
+++ b/clang/include/clang/Index/IndexSymbol.h
@@ -57,6 +57,8 @@ enum class SymbolKind : uint8_t {
   TemplateTypeParm,
   TemplateTemplateParm,
   NonTypeTemplateParm,
+
+  Concept, /// C++20 concept.
 };
 
 enum class SymbolLanguage : uint8_t {

diff  --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
index fa35f749d0284..ecf4b8bca74ba 100644
--- a/clang/lib/Index/IndexBody.cpp
+++ b/clang/lib/Index/IndexBody.cpp
@@ -7,8 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "IndexingContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/ASTConcept.h"
 #include "clang/AST/ASTLambda.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
 
 using namespace clang;
 using namespace clang::index;
@@ -455,10 +459,10 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
   }
 
   bool VisitParmVarDecl(ParmVarDecl* D) {
-    // Index the parameters of lambda expression.
+    // Index the parameters of lambda expression and requires expression.
     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
       const auto *DC = D->getDeclContext();
-      if (DC && isLambdaCallOperator(DC))
+      if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC)))
         IndexCtx.handleDecl(D);
     }
     return true;
@@ -472,6 +476,21 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
                                Relations, E);
     return true;
   }
+
+  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
+    IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
+                             Parent, ParentDC);
+    return true;
+  }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+    // This handles references in return type requirements of RequiresExpr.
+    // E.g. `requires (T x) { {*x} -> ConceptRef }`
+    if (auto *C = D->getTypeConstraint())
+      IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
+                               Parent, ParentDC);
+    return true;
+  }
 };
 
 } // anonymous namespace

diff  --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp
index 635174500cee7..882e02836d4fb 100644
--- a/clang/lib/Index/IndexDecl.cpp
+++ b/clang/lib/Index/IndexDecl.cpp
@@ -7,10 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "IndexingContext.h"
+#include "clang/AST/ASTConcept.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexSymbol.h"
 
 using namespace clang;
 using namespace index;
@@ -129,6 +132,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
         }
       }
     }
+    if (auto *C = D->getTrailingRequiresClause())
+      IndexCtx.indexBody(C, Parent);
   }
 
   bool handleObjCMethod(const ObjCMethodDecl *D,
@@ -688,36 +693,52 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
     return true;
   }
 
-  bool VisitTemplateDecl(const TemplateDecl *D) {
+  void indexTemplateParameters(TemplateParameterList *Params,
+                               const NamedDecl *Parent) {
+    for (const NamedDecl *TP : *Params) {
+      if (IndexCtx.shouldIndexTemplateParameters())
+        IndexCtx.handleDecl(TP);
+      if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
+        if (TTP->hasDefaultArgument())
+          IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
+        if (auto *C = TTP->getTypeConstraint())
+          IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
+                                   Parent, TTP->getLexicalDeclContext());
+      } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
+        if (NTTP->hasDefaultArgument())
+          IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
+      } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
+        if (TTPD->hasDefaultArgument())
+          handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
+                                    TP->getLexicalDeclContext());
+      }
+    }
+    if (auto *R = Params->getRequiresClause())
+      IndexCtx.indexBody(R, Parent);
+  }
 
+  bool VisitTemplateDecl(const TemplateDecl *D) {
     const NamedDecl *Parent = D->getTemplatedDecl();
     if (!Parent)
       return true;
 
     // Index the default values for the template parameters.
-    if (D->getTemplateParameters() &&
-        shouldIndexTemplateParameterDefaultValue(Parent)) {
-      const TemplateParameterList *Params = D->getTemplateParameters();
-      for (const NamedDecl *TP : *Params) {
-        if (IndexCtx.shouldIndexTemplateParameters())
-          IndexCtx.handleDecl(TP);
-        if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
-          if (TTP->hasDefaultArgument())
-            IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
-        } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
-          if (NTTP->hasDefaultArgument())
-            IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
-        } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
-          if (TTPD->hasDefaultArgument())
-            handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
-                                      TP->getLexicalDeclContext());
-        }
-      }
+    auto *Params = D->getTemplateParameters();
+    if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
+      indexTemplateParameters(Params, Parent);
     }
 
     return Visit(Parent);
   }
 
+  bool VisitConceptDecl(const ConceptDecl *D) {
+    if (auto *Params = D->getTemplateParameters())
+      indexTemplateParameters(Params, D);
+    if (auto *E = D->getConstraintExpr())
+      IndexCtx.indexBody(E, D);
+    return IndexCtx.handleDecl(D);
+  }
+
   bool VisitFriendDecl(const FriendDecl *D) {
     if (auto ND = D->getFriendDecl()) {
       // FIXME: Ignore a class template in a dependent context, these are not

diff  --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp
index 68e457de52654..a40c218a3c438 100644
--- a/clang/lib/Index/IndexSymbol.cpp
+++ b/clang/lib/Index/IndexSymbol.cpp
@@ -371,6 +371,9 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
     case Decl::NonTypeTemplateParm:
       Info.Kind = SymbolKind::NonTypeTemplateParm;
       break;
+    case Decl::Concept:
+      Info.Kind = SymbolKind::Concept;
+      break;
     // Other decls get the 'unknown' kind.
     default:
       break;
@@ -534,6 +537,8 @@ StringRef index::getSymbolKindString(SymbolKind K) {
   case SymbolKind::TemplateTypeParm: return "template-type-param";
   case SymbolKind::TemplateTemplateParm: return "template-template-param";
   case SymbolKind::NonTypeTemplateParm: return "non-type-template-param";
+  case SymbolKind::Concept:
+    return "concept";
   }
   llvm_unreachable("invalid symbol kind");
 }

diff  --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index ec4ca23942cad..b986ccde57452 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -7,7 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "IndexingContext.h"
+#include "clang/AST/ASTConcept.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeLoc.h"
 #include "llvm/ADT/ScopeExit.h"
 
 using namespace clang;
@@ -77,6 +80,13 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
     return true;
   }
 
+  bool VisitAutoTypeLoc(AutoTypeLoc TL) {
+    if (auto *C = TL.getNamedConcept())
+      return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent,
+                                      ParentDC);
+    return true;
+  }
+
   bool traverseParamVarHelper(ParmVarDecl *D) {
     TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
     if (D->getTypeSourceInfo())

diff  --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp
index 8a962a055bac9..ca8b144a431c0 100644
--- a/clang/lib/Index/IndexingContext.cpp
+++ b/clang/lib/Index/IndexingContext.cpp
@@ -86,7 +86,6 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
        isa<TemplateTemplateParmDecl>(D))) {
     return true;
   }
-
   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
                               RefE, RefD, DC);
 }
@@ -259,12 +258,9 @@ static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, AST
   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
 
-  if (isa<TypedefNameDecl>(D) ||
-      isa<EnumConstantDecl>(D) ||
-      isa<FieldDecl>(D) ||
-      isa<MSPropertyDecl>(D) ||
-      isa<ObjCImplDecl>(D) ||
-      isa<ObjCPropertyImplDecl>(D))
+  if (isa<TypedefNameDecl>(D) || isa<EnumConstantDecl>(D) ||
+      isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || isa<ObjCImplDecl>(D) ||
+      isa<ObjCPropertyImplDecl>(D) || isa<ConceptDecl>(D))
     return true;
 
   return false;

diff  --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 129114ebfaedc..c606d8521bee8 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -103,6 +103,7 @@ class USRGenerator : public ConstDeclVisitor<USRGenerator> {
   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
   void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
   void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
+  void VisitConceptDecl(const ConceptDecl *D);
 
   void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
     IgnoreResults = true; // No USRs for linkage specs themselves.
@@ -1007,7 +1008,13 @@ void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenam
   Out << D->getName(); // Simple name.
 }
 
-
+void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {
+  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+    return;
+  VisitDeclContext(D->getDeclContext());
+  Out << "@CT@";
+  EmitDeclName(D);
+}
 
 //===----------------------------------------------------------------------===//
 // USR generation functions.

diff  --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp
index fa40687495ca1..2e87689f65661 100644
--- a/clang/tools/libclang/CXIndexDataConsumer.cpp
+++ b/clang/tools/libclang/CXIndexDataConsumer.cpp
@@ -1249,6 +1249,7 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage
   case SymbolKind::TemplateTypeParm:
   case SymbolKind::TemplateTemplateParm:
   case SymbolKind::NonTypeTemplateParm:
+  case SymbolKind::Concept:
     return CXIdxEntity_Unexposed;
 
   case SymbolKind::Enum: return CXIdxEntity_Enum;


        


More information about the cfe-commits mailing list