]> granicus.if.org Git - clang/commitdiff
[index] Enhance indexing for module references
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 18 Sep 2018 15:02:56 +0000 (15:02 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 18 Sep 2018 15:02:56 +0000 (15:02 +0000)
* Create a USR for the occurrences of the 'module' symbol kind
* Record module references for each identifier in an import declaration

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342484 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/Index/IndexDataConsumer.h
include/clang/Index/USRGeneration.h
lib/Index/IndexingAction.cpp
lib/Index/IndexingContext.cpp
lib/Index/USRGeneration.cpp
test/Index/Core/Inputs/module/SubModA.h [new file with mode: 0644]
test/Index/Core/Inputs/module/SubSubModA.h [new file with mode: 0644]
test/Index/Core/Inputs/module/module.modulemap
test/Index/Core/index-with-module.m
tools/c-index-test/core_main.cpp
tools/libclang/CXIndexDataConsumer.cpp
tools/libclang/CXIndexDataConsumer.h

index 6e11455661a09001f06c418a92e2ece7d0975fca..c79f6be3e13bfe653fcfead069f33c55e6c41356 100644 (file)
@@ -50,7 +50,12 @@ public:
                                     SourceLocation Loc);
 
   /// \returns true to continue indexing, or false to abort.
+  ///
+  /// This will be called for each module reference in an import decl.
+  /// For "@import MyMod.SubMod", there will be a call for 'MyMod' with the
+  /// 'reference' role, and a call for 'SubMod' with the 'declaration' role.
   virtual bool handleModuleOccurence(const ImportDecl *ImportD,
+                                     const Module *Mod,
                                      SymbolRoleSet Roles, SourceLocation Loc);
 
   virtual void finish() {}
index 1ece321746a60066238d0ee4f9ee094e9200acbe..4987cd6c5e4336433b4a70a9d477296ec6dbd4d9 100644 (file)
@@ -16,6 +16,7 @@
 namespace clang {
 class Decl;
 class MacroDefinitionRecord;
+class Module;
 class SourceLocation;
 class SourceManager;
 
@@ -70,6 +71,22 @@ bool generateUSRForMacro(const MacroDefinitionRecord *MD,
 bool generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
                          const SourceManager &SM, SmallVectorImpl<char> &Buf);
 
+/// Generate a USR for a module, including the USR prefix.
+/// \returns true on error, false on success.
+bool generateFullUSRForModule(const Module *Mod, raw_ostream &OS);
+
+/// Generate a USR for a top-level module name, including the USR prefix.
+/// \returns true on error, false on success.
+bool generateFullUSRForTopLevelModuleName(StringRef ModName, raw_ostream &OS);
+
+/// Generate a USR fragment for a module.
+/// \returns true on error, false on success.
+bool generateUSRFragmentForModule(const Module *Mod, raw_ostream &OS);
+
+/// Generate a USR fragment for a module name.
+/// \returns true on error, false on success.
+bool generateUSRFragmentForModuleName(StringRef ModName, raw_ostream &OS);
+
 } // namespace index
 } // namespace clang
 
index cb5c951f38a56550d18a3214a4728c69bf4e297b..5cdec4b4528ef49f831d0c72aef19f9c47ab7158 100644 (file)
@@ -37,6 +37,7 @@ bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
 }
 
 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+                                              const Module *Mod,
                                               SymbolRoleSet Roles,
                                               SourceLocation Loc) {
   return true;
index 333f9dc3091bbb12a1ec9c6e731666050ff550db..bba6c8390b569dc718cf688062b6cc9d28b19fda 100644 (file)
@@ -80,11 +80,27 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
                               RefE, RefD, DC);
 }
 
+static void reportModuleReferences(const Module *Mod,
+                                   ArrayRef<SourceLocation> IdLocs,
+                                   const ImportDecl *ImportD,
+                                   IndexDataConsumer &DataConsumer) {
+  if (!Mod)
+    return;
+  reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
+                         DataConsumer);
+  DataConsumer.handleModuleOccurence(ImportD, Mod,
+                                     (SymbolRoleSet)SymbolRole::Reference,
+                                     IdLocs.back());
+}
+
 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
+  if (ImportD->isInvalidDecl())
+    return true;
+
   SourceLocation Loc;
   auto IdLocs = ImportD->getIdentifierLocs();
   if (!IdLocs.empty())
-    Loc = IdLocs.front();
+    Loc = IdLocs.back();
   else
     Loc = ImportD->getLocation();
 
@@ -108,11 +124,17 @@ bool IndexingContext::importedModule(const ImportDecl *ImportD) {
     }
   }
 
+  const Module *Mod = ImportD->getImportedModule();
+  if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
+    reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
+                           DataConsumer);
+  }
+
   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
   if (ImportD->isImplicit())
     Roles |= (unsigned)SymbolRole::Implicit;
 
-  return DataConsumer.handleModuleOccurence(ImportD, Roles, Loc);
+  return DataConsumer.handleModuleOccurence(ImportD, Mod, Roles, Loc);
 }
 
 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
index 62ae7108fc67dd95dcf26ce65a307a73bb3a9939..8194c9508fb7e632559f0926750a6aac05a28bda 100644 (file)
@@ -1094,3 +1094,29 @@ bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
   Out << MacroName;
   return false;
 }
+
+bool clang::index::generateFullUSRForModule(const Module *Mod,
+                                            raw_ostream &OS) {
+  if (!Mod->Parent)
+    return generateFullUSRForTopLevelModuleName(Mod->Name, OS);
+  if (generateFullUSRForModule(Mod->Parent, OS))
+    return true;
+  return generateUSRFragmentForModule(Mod, OS);
+}
+
+bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,
+                                                        raw_ostream &OS) {
+  OS << getUSRSpacePrefix();
+  return generateUSRFragmentForModuleName(ModName, OS);
+}
+
+bool clang::index::generateUSRFragmentForModule(const Module *Mod,
+                                                raw_ostream &OS) {
+  return generateUSRFragmentForModuleName(Mod->Name, OS);
+}
+
+bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,
+                                                    raw_ostream &OS) {
+  OS << "@M@" << ModName;
+  return false;
+}
diff --git a/test/Index/Core/Inputs/module/SubModA.h b/test/Index/Core/Inputs/module/SubModA.h
new file mode 100644 (file)
index 0000000..59d243e
--- /dev/null
@@ -0,0 +1,2 @@
+
+void SubModA_func(void);
diff --git a/test/Index/Core/Inputs/module/SubSubModA.h b/test/Index/Core/Inputs/module/SubSubModA.h
new file mode 100644 (file)
index 0000000..51ffa91
--- /dev/null
@@ -0,0 +1,2 @@
+
+void SubSubModA_func(void);
index a132562eafd8b7b280494c3349d2522d7dde7a0a..180a4aad36dcdc0696c10f0bb018cf26ba8f94a1 100644 (file)
@@ -1 +1,11 @@
-module ModA { header "ModA.h" export * }
+module ModA {
+  header "ModA.h" export *
+
+  module SubModA {
+    header "SubModA.h"
+
+    module SubSubModA {
+      header "SubSubModA.h"
+    }
+  }
+}
index c83de63701e1055625454dfea521857078b9a2c6..ca89c2e1de382b2ec3e8e12c428d9d38c6948adf 100644 (file)
@@ -1,11 +1,17 @@
 // RUN: rm -rf %t.mcp
 // RUN: c-index-test core -print-source-symbols -dump-imported-module-files -- %s -I %S/Inputs/module -fmodules -fmodules-cache-path=%t.mcp | FileCheck %s
 
-// CHECK: [[@LINE+1]]:9 | module/C | ModA | Decl |
+// CHECK: [[@LINE+1]]:9 | module/C | ModA | [[ModA_USR:c:@M@ModA]] | Decl |
 @import ModA;
-// CHECK: [[@LINE+1]]:1 | module/C | ModA | Decl,Impl |
+// CHECK: [[@LINE+1]]:1 | module/C | ModA | [[ModA_USR]] | Decl,Impl |
 #include "ModA.h"
 
+@import ModA.SubModA.SubSubModA;
+// CHECK: [[@LINE-1]]:9 | module/C | ModA | [[ModA_USR]] | Ref |
+// CHECK: [[@LINE-2]]:14 | module/C | ModA.SubModA | c:@M@ModA@M@SubModA | Ref |
+// CHECK: [[@LINE-3]]:22 | module/C | ModA.SubModA.SubSubModA | [[SubSubModA_USR:c:@M@ModA@M@SubModA@M@SubSubModA]] | Decl |
+#include "SubSubModA.h" // CHECK: [[@LINE]]:1 | module/C | ModA.SubModA.SubSubModA | [[SubSubModA_USR]] | Decl,Impl |
+
 void foo() {
   // CHECK: [[@LINE+1]]:3 | function/C | ModA_func | c:@F@ModA_func | {{.*}} | Ref,Call,RelCall,RelCont | rel: 1
   ModA_func();
index 9921a403a4b75c05638b786b647a2c3087939783..b9c0f19a7fccb72bdf94f85e2ac74069f73e8d39 100644 (file)
@@ -74,6 +74,7 @@ static cl::opt<std::string>
 static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
 static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
                                   raw_ostream &OS);
+static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS);
 
 namespace {
 
@@ -132,8 +133,9 @@ public:
     return true;
   }
 
-  bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles,
-                             SourceLocation Loc) override {
+  bool handleModuleOccurence(const ImportDecl *ImportD,
+                             const clang::Module *Mod,
+                             SymbolRoleSet Roles, SourceLocation Loc) override {
     ASTContext &Ctx = ImportD->getASTContext();
     SourceManager &SM = Ctx.getSourceManager();
 
@@ -146,7 +148,8 @@ public:
     printSymbolInfo(getSymbolInfo(ImportD), OS);
     OS << " | ";
 
-    OS << ImportD->getImportedModule()->getFullModuleName() << " | ";
+    printSymbolNameAndUSR(Mod, OS);
+    OS << " | ";
 
     printSymbolRoles(Roles, OS);
     OS << " |\n";
@@ -308,6 +311,12 @@ static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
   }
 }
 
+static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS) {
+  assert(Mod);
+  OS << Mod->getFullModuleName() << " | ";
+  generateFullUSRForModule(Mod, OS);
+}
+
 //===----------------------------------------------------------------------===//
 // Command line processing.
 //===----------------------------------------------------------------------===//
index 00ade2ee8f01a0f6904904bbde9b8646ea5a73d1..3dec36a5daebb5c09f7f9a8040c779531c3bc440 100644 (file)
@@ -222,9 +222,11 @@ bool CXIndexDataConsumer::handleDeclOccurence(
 }
 
 bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+                                                const Module *Mod,
                                                 SymbolRoleSet Roles,
                                                 SourceLocation Loc) {
-  IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
+  if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
+    IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
   return !shouldAbort();
 }
 
index 19e39b281ab0fe0f48d9521fbeb96128572a7b68..5c1ce80b2f4993dff67aa7fa41020891ecba0a54 100644 (file)
@@ -467,7 +467,7 @@ private:
                            ArrayRef<index::SymbolRelation> Relations,
                            SourceLocation Loc, ASTNodeInfo ASTNode) override;
 
-  bool handleModuleOccurence(const ImportDecl *ImportD,
+  bool handleModuleOccurence(const ImportDecl *ImportD, const Module *Mod,
                              index::SymbolRoleSet Roles,
                              SourceLocation Loc) override;