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

The only relation currently collected is RelationBaseOf, because this is
all we need for type hierarchy subtypes. Additional relations can be
collected in the future as the need arises.

This patch builds on D59407 <https://reviews.llvm.org/D59407> and D62459 
<https://reviews.llvm.org/D62459>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62471

Files:
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h

Index: clang-tools-extra/clangd/index/SymbolCollector.h
===================================================================
--- clang-tools-extra/clangd/index/SymbolCollector.h
+++ clang-tools-extra/clangd/index/SymbolCollector.h
@@ -110,6 +110,7 @@
 
   SymbolSlab takeSymbols() { return std::move(Symbols).build(); }
   RefSlab takeRefs() { return std::move(Refs).build(); }
+  RelationSlab takeRelations() { return std::move(Relations).build(); }
 
   void finish() override;
 
@@ -117,6 +118,8 @@
   const Symbol *addDeclaration(const NamedDecl &, SymbolID,
                                bool IsMainFileSymbol);
   void addDefinition(const NamedDecl &, const Symbol &DeclSymbol);
+  void processRelations(const NamedDecl &ND, const SymbolID &ID,
+                        ArrayRef<index::SymbolRelation> Relations);
 
   llvm::Optional<std::string> getIncludeHeader(llvm::StringRef QName, FileID);
   bool isSelfContainedHeader(FileID);
@@ -135,6 +138,8 @@
   // Only symbols declared in preamble (from #include) and referenced from the
   // main file will be included.
   RefSlab::Builder Refs;
+  // All relations collected from the AST.
+  RelationSlab::Builder Relations;
   ASTContext *ASTCtx;
   std::shared_ptr<Preprocessor> PP;
   std::shared_ptr<GlobalCodeCompletionAllocator> CompletionAllocator;
Index: clang-tools-extra/clangd/index/SymbolCollector.cpp
===================================================================
--- clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -291,6 +291,12 @@
       SM.getFileID(SpellingLoc) == SM.getMainFileID())
     ReferencedDecls.insert(ND);
 
+  auto ID = getSymbolID(ND);
+  if (!ID)
+    return true;
+
+  processRelations(*ND, *ID, Relations);
+
   bool CollectRef = static_cast<unsigned>(Opts.RefFilter) & Roles;
   bool IsOnlyRef =
       !(Roles & (static_cast<unsigned>(index::SymbolRole::Declaration) |
@@ -315,10 +321,6 @@
   if (IsOnlyRef)
     return true;
 
-  auto ID = getSymbolID(ND);
-  if (!ID)
-    return true;
-
   // FIXME: ObjCPropertyDecl are not properly indexed here:
   // - ObjCPropertyDecl may have an OrigD of ObjCPropertyImplDecl, which is
   // not a NamedDecl.
@@ -338,6 +340,7 @@
 
   if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
     addDefinition(*OriginalDecl, *BasicSymbol);
+
   return true;
 }
 
@@ -416,8 +419,43 @@
   return true;
 }
 
-void SymbolCollector::setIncludeLocation(const Symbol &S,
-                                         SourceLocation Loc) {
+void SymbolCollector::processRelations(
+    const NamedDecl &ND, const SymbolID &ID,
+    ArrayRef<index::SymbolRelation> Relations) {
+  // Store subtype relations.
+  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(&ND);
+  if (!RD)
+    return;
+
+  for (const auto &R : Relations) {
+    if (!(R.Roles & static_cast<unsigned>(index::SymbolRole::RelationBaseOf))) {
+      continue;
+    }
+    const Decl *Parent = R.RelatedSymbol;
+
+    if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Parent)) {
+      if (!CTSD->isExplicitSpecialization()) {
+        Parent = CTSD->getSpecializedTemplate();
+      }
+    }
+    if (auto ParentID = getSymbolID(Parent)) {
+      // We are a subtype to each of our parents.
+      // TODO: There may be cases where the parent type is not indexed for some
+      // reason (e.g. currently we don't index explicit class template
+      // specializations). Those cases should probably be removed in due course,
+      // but for now there are two possible ways to handle it:
+      //   (A) Avoid storing the relationship in such cases.
+      //   (B) Store it anyways. Clients will likely lookup() the SymbolID
+      //       in the index and find nothing, but that's a situation they
+      //       probably need to handle for other reasons anyways.
+      // We currently do (B) because it's simpler.
+      this->Relations.insert(
+          Relation{ID, index::SymbolRole::RelationBaseOf, *ParentID});
+    }
+  }
+}
+
+void SymbolCollector::setIncludeLocation(const Symbol &S, SourceLocation Loc) {
   if (Opts.CollectIncludePath)
     if (shouldCollectIncludePath(S.SymInfo.Kind))
       // Use the expansion location to get the #include header since this is
@@ -681,7 +719,7 @@
   if (!Line.consume_front("#"))
     return false;
   Line = Line.ltrim();
-  if (! Line.startswith("error"))
+  if (!Line.startswith("error"))
     return false;
   return Line.contains_lower("includ"); // Matches "include" or "including".
 }
@@ -689,7 +727,7 @@
 bool SymbolCollector::isDontIncludeMeHeader(llvm::StringRef Content) {
   llvm::StringRef Line;
   // Only sniff up to 100 lines or 10KB.
-  Content = Content.take_front(100*100);
+  Content = Content.take_front(100 * 100);
   for (unsigned I = 0; I < 100 && !Content.empty(); ++I) {
     std::tie(Line, Content) = Content.split('\n');
     if (isIf(Line) && isErrorAboutInclude(Content.split('\n').first))
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to