Merge remote-tracking branch 'origin/swift-4.0-branch' into stable
* origin/swift-4.0-branch:
[c-index-test] CMake: add missing reference to clangSerialization library.
[index] CMake: add missing reference to clangSerialization library.
[c-index-test] Provide capability to index module file imports and dump their input files.
[c-index-test] Provide capability for 'c-index-test core' to dump symbol information from a PCH/module file.
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index b1cdb46..03961f1 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -519,6 +519,8 @@
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+ IntrusiveRefCntPtr<ASTReader> getASTReader() const;
+
StringRef getOriginalSourceFileName() {
return OriginalSourceFile;
}
diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h
index e2e63dc..8eed33c 100644
--- a/include/clang/Index/IndexingAction.h
+++ b/include/clang/Index/IndexingAction.h
@@ -14,9 +14,14 @@
#include <memory>
namespace clang {
+ class ASTReader;
class ASTUnit;
class FrontendAction;
+namespace serialization {
+ class ModuleFile;
+}
+
namespace index {
class IndexDataConsumer;
@@ -42,6 +47,11 @@
std::shared_ptr<IndexDataConsumer> DataConsumer,
IndexingOptions Opts);
+void indexModuleFile(serialization::ModuleFile &Mod,
+ ASTReader &Reader,
+ std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexingOptions Opts);
+
} // namespace index
} // namespace clang
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 93994e2..3282eb0 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1268,6 +1268,7 @@
llvm::iterator_range<PreprocessingRecord::iterator>
getModulePreprocessedEntities(ModuleFile &Mod) const;
+public:
class ModuleDeclIterator
: public llvm::iterator_adaptor_base<
ModuleDeclIterator, const serialization::LocalDeclID *,
@@ -1298,6 +1299,7 @@
llvm::iterator_range<ModuleDeclIterator>
getModuleFileLevelDecls(ModuleFile &Mod);
+private:
void PassInterestingDeclsToConsumer();
void PassInterestingDeclToConsumer(Decl *D);
@@ -2189,6 +2191,12 @@
/// \brief Loads comments ranges.
void ReadComments() override;
+ /// Visit all the input files of the given module file.
+ void visitInputFiles(serialization::ModuleFile &MF,
+ bool IncludeSystem, bool Complain,
+ llvm::function_ref<void(const serialization::InputFile &IF,
+ bool isSystem)> Visitor);
+
bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
};
diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h
index 58b3149..f0629ed 100644
--- a/include/clang/Serialization/Module.h
+++ b/include/clang/Serialization/Module.h
@@ -210,6 +210,10 @@
/// \brief The input files that have been loaded from this AST file.
std::vector<InputFile> InputFilesLoaded;
+ // All user input files reside at the index range [0, NumUserInputFiles), and
+ // system input files reside at [NumUserInputFiles, InputFilesLoaded.size()).
+ unsigned NumUserInputFiles = 0;
+
/// \brief If non-zero, specifies the time when we last validated input
/// files. Zero means we never validated them.
///
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index d892996..c29b908 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -619,6 +619,10 @@
StoredDiags.emplace_back(Level, Info);
}
+IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {
+ return Reader;
+}
+
ASTMutationListener *ASTUnit::getASTMutationListener() {
if (WriterData)
return &WriterData->Writer;
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
index 8f51ccb..c9fbfaf 100644
--- a/lib/Index/CMakeLists.txt
+++ b/lib/Index/CMakeLists.txt
@@ -24,5 +24,6 @@
clangFormat
clangFrontend
clangRewrite
+ clangSerialization
clangToolingCore
)
diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp
index d744293..cac24d4 100644
--- a/lib/Index/IndexingAction.cpp
+++ b/lib/Index/IndexingAction.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Serialization/ASTReader.h"
using namespace clang;
using namespace clang::index;
@@ -173,4 +174,20 @@
IndexCtx.setASTContext(Unit.getASTContext());
DataConsumer->initialize(Unit.getASTContext());
indexTranslationUnit(Unit, IndexCtx);
+ DataConsumer->finish();
+}
+
+void index::indexModuleFile(serialization::ModuleFile &Mod,
+ ASTReader &Reader,
+ std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexingOptions Opts) {
+ ASTContext &Ctx = Reader.getContext();
+ IndexingContext IndexCtx(Opts, *DataConsumer);
+ IndexCtx.setASTContext(Ctx);
+ DataConsumer->initialize(Ctx);
+
+ for (const Decl *D :Reader.getModuleFileLevelDecls(Mod)) {
+ IndexCtx.indexTopLevelDecl(D);
+ }
+ DataConsumer->finish();
}
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index da822c3..00db74a 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2513,6 +2513,7 @@
F.InputFileOffsets =
(const llvm::support::unaligned_uint64_t *)Blob.data();
F.InputFilesLoaded.resize(NumInputs);
+ F.NumUserInputFiles = NumUserInputs;
break;
}
}
@@ -8534,6 +8535,21 @@
}
}
+void ASTReader::visitInputFiles(serialization::ModuleFile &MF,
+ bool IncludeSystem, bool Complain,
+ llvm::function_ref<void(const serialization::InputFile &IF,
+ bool isSystem)> Visitor) {
+ unsigned NumUserInputs = MF.NumUserInputFiles;
+ unsigned NumInputs = MF.InputFilesLoaded.size();
+ assert(NumUserInputs <= NumInputs);
+ unsigned N = IncludeSystem ? NumInputs : NumUserInputs;
+ for (unsigned I = 0; I < N; ++I) {
+ bool IsSystem = I >= NumUserInputs;
+ InputFile IF = getInputFile(MF, I+1, Complain);
+ Visitor(IF, IsSystem);
+ }
+}
+
std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
// If we know the owning module, use it.
if (Module *M = D->getImportedOwningModule())
diff --git a/test/Index/Core/index-pch.c b/test/Index/Core/index-pch.c
new file mode 100644
index 0000000..773cfc5
--- /dev/null
+++ b/test/Index/Core/index-pch.c
@@ -0,0 +1,13 @@
+// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s
+// RUN: %clang_cc1 -emit-pch %s -o %t.pch
+// RUN: c-index-test core -print-source-symbols -module-file %t.pch | FileCheck %s
+
+// CHECK: [[@LINE+1]]:6 | function/C | test1 | [[TEST1_USR:.*]] | [[TEST1_CG:.*]] | Decl | rel: 0
+void test1();
+
+// CHECK: [[@LINE+1]]:20 | function/C | test2 | [[TEST2_USR:.*]] | {{.*}} | Def | rel: 0
+static inline void test2() {
+ // CHECK: [[@LINE+2]]:3 | function/C | test1 | [[TEST1_USR]] | [[TEST1_CG]] | Ref,Call,RelCall,RelCont | rel: 1
+ // CHECK-NEXT: RelCall,RelCont | test2 | [[TEST2_USR]]
+ test1();
+}
diff --git a/test/Index/Core/index-with-module.m b/test/Index/Core/index-with-module.m
index e50b247..c83de63 100644
--- a/test/Index/Core/index-with-module.m
+++ b/test/Index/Core/index-with-module.m
@@ -1,5 +1,5 @@
// RUN: rm -rf %t.mcp
-// RUN: c-index-test core -print-source-symbols -- %s -I %S/Inputs/module -fmodules -fmodules-cache-path=%t.mcp | FileCheck %s
+// 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 |
@import ModA;
@@ -10,3 +10,9 @@
// CHECK: [[@LINE+1]]:3 | function/C | ModA_func | c:@F@ModA_func | {{.*}} | Ref,Call,RelCall,RelCont | rel: 1
ModA_func();
}
+
+// CHECK: ==== Module ModA ====
+// CHECK: 2:6 | function/C | ModA_func | c:@F@ModA_func | {{.*}} | Decl | rel: 0
+// CHECK: ---- Module Inputs ----
+// CHECK: user | {{.*}}ModA.h
+// CHECK: user | {{.*}}module.modulemap
diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt
index e0df503..7244e2c 100644
--- a/tools/c-index-test/CMakeLists.txt
+++ b/tools/c-index-test/CMakeLists.txt
@@ -24,8 +24,10 @@
libclang
clangAST
clangBasic
+ clangCodeGen
clangFrontend
clangIndex
+ clangSerialization
)
endif()
diff --git a/tools/c-index-test/core_main.cpp b/tools/c-index-test/core_main.cpp
index 0ab24fb..f371870 100644
--- a/tools/c-index-test/core_main.cpp
+++ b/tools/c-index-test/core_main.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
@@ -15,6 +16,7 @@
#include "clang/Index/IndexDataConsumer.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Index/CodegenNameGenerator.h"
+#include "clang/Serialization/ASTReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
@@ -49,6 +51,17 @@
"invocation\n"
);
+static cl::opt<bool>
+DumpModuleImports("dump-imported-module-files",
+ cl::desc("Print symbols and input files from imported modules"));
+
+static cl::opt<std::string>
+ModuleFilePath("module-file",
+ cl::desc("Path to module file to print symbols from"));
+static cl::opt<std::string>
+ ModuleFormat("fmodule-format", cl::init("raw"),
+ cl::desc("Container format for clang modules and PCH, 'raw' or 'obj'"));
+
}
} // anonymous namespace
@@ -134,7 +147,19 @@
// Print Source Symbols
//===----------------------------------------------------------------------===//
-static bool printSourceSymbols(ArrayRef<const char *> Args) {
+static void dumpModuleFileInputs(serialization::ModuleFile &Mod,
+ ASTReader &Reader,
+ raw_ostream &OS) {
+ OS << "---- Module Inputs ----\n";
+ Reader.visitInputFiles(Mod, /*IncludeSystem=*/true, /*Complain=*/false,
+ [&](const serialization::InputFile &IF, bool isSystem) {
+ OS << (isSystem ? "system" : "user") << " | ";
+ OS << IF.getFile()->getName() << '\n';
+ });
+}
+
+static bool printSourceSymbols(ArrayRef<const char *> Args,
+ bool dumpModuleImports) {
SmallVector<const char *, 4> ArgsWithProgName;
ArgsWithProgName.push_back("clang");
ArgsWithProgName.append(Args.begin(), Args.end());
@@ -144,7 +169,8 @@
if (!CInvok)
return true;
- auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(outs());
+ raw_ostream &OS = outs();
+ auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(OS);
IndexingOptions IndexOpts;
std::unique_ptr<FrontendAction> IndexAction;
IndexAction = createIndexingAction(DataConsumer, IndexOpts,
@@ -157,6 +183,50 @@
if (!Unit)
return true;
+ if (dumpModuleImports) {
+ if (auto Reader = Unit->getASTReader()) {
+ Reader->getModuleManager().visit([&](serialization::ModuleFile &Mod) -> bool {
+ OS << "==== Module " << Mod.ModuleName << " ====\n";
+ indexModuleFile(Mod, *Reader, DataConsumer, IndexOpts);
+ dumpModuleFileInputs(Mod, *Reader, OS);
+ return true; // skip module dependencies.
+ });
+ }
+ }
+
+ return false;
+}
+
+static bool printSourceSymbolsFromModule(StringRef modulePath,
+ StringRef format) {
+ FileSystemOptions FileSystemOpts;
+ auto pchContOps = std::make_shared<PCHContainerOperations>();
+ // Register the support for object-file-wrapped Clang modules.
+ pchContOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>());
+ auto pchRdr = pchContOps->getReaderOrNull(format);
+ if (!pchRdr) {
+ errs() << "unknown module format: " << format << '\n';
+ return true;
+ }
+
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+ CompilerInstance::createDiagnostics(new DiagnosticOptions());
+ std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
+ modulePath, *pchRdr, Diags,
+ FileSystemOpts, /*UseDebugInfo=*/false,
+ /*OnlyLocalDecls=*/true, None,
+ /*CaptureDiagnostics=*/false,
+ /*AllowPCHWithCompilerErrors=*/true,
+ /*UserFilesAreVolatile=*/false);
+ if (!AU) {
+ errs() << "failed to create TU for: " << modulePath << '\n';
+ return true;
+ }
+
+ auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(outs());
+ IndexingOptions IndexOpts;
+ indexASTUnit(*AU, DataConsumer, IndexOpts);
+
return false;
}
@@ -219,11 +289,15 @@
}
if (options::Action == ActionType::PrintSourceSymbols) {
+ if (!options::ModuleFilePath.empty()) {
+ return printSourceSymbolsFromModule(options::ModuleFilePath,
+ options::ModuleFormat);
+ }
if (CompArgs.empty()) {
errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n";
return 1;
}
- return printSourceSymbols(CompArgs);
+ return printSourceSymbols(CompArgs, options::DumpModuleImports);
}
return 0;