From c1d22393628a145e54396c0ac66e9625d13a7658 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 13 Mar 2013 21:13:43 +0000 Subject: [PATCH] [Modules] Resolve top-headers of modules lazily. This allows resolving top-header filenames of modules to FileEntries when we need them, not eagerly. Note that that this breaks ABI for libclang functions clang_Module_getTopLevelHeader / clang_Module_getNumTopLevelHeaders but this is fine because they are experimental and not widely used yet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176975 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 8 +++++--- include/clang/Basic/Module.h | 26 ++++++++++++++++++++++---- lib/Basic/Module.cpp | 14 ++++++++++++++ lib/Frontend/FrontendActions.cpp | 6 +++--- lib/Lex/ModuleMap.cpp | 2 +- lib/Serialization/ASTReader.cpp | 4 +--- lib/Serialization/ASTWriter.cpp | 6 ++++-- tools/c-index-test/c-index-test.c | 4 ++-- tools/libclang/CIndex.cpp | 20 +++++++++++++------- 9 files changed, 65 insertions(+), 25 deletions(-) diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 07c0ffb443..71d3443ae6 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 14 +#define CINDEX_VERSION_MINOR 15 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -3347,7 +3347,8 @@ CINDEX_LINKAGE CXString clang_Module_getFullName(CXModule Module); * * \returns the number of top level headers associated with this module. */ -CINDEX_LINKAGE unsigned clang_Module_getNumTopLevelHeaders(CXModule Module); +CINDEX_LINKAGE unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit, + CXModule Module); /** * \param Module a module object. @@ -3357,7 +3358,8 @@ CINDEX_LINKAGE unsigned clang_Module_getNumTopLevelHeaders(CXModule Module); * \returns the specified top level header associated with the module. */ CINDEX_LINKAGE -CXFile clang_Module_getTopLevelHeader(CXModule Module, unsigned Index); +CXFile clang_Module_getTopLevelHeader(CXTranslationUnit, + CXModule Module, unsigned Index); /** * @} diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index db636e5cd4..5f081e0f56 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -34,6 +34,7 @@ namespace clang { class DirectoryEntry; class FileEntry; +class FileManager; class LangOptions; class TargetInfo; @@ -67,7 +68,13 @@ private: /// \brief The AST file if this is a top-level module which has a /// corresponding serialized AST file, or null otherwise. const FileEntry *ASTFile; - + + /// \brief The top-level headers associated with this module. + llvm::SmallSetVector TopHeaders; + + /// \brief top-level header filenames that aren't resolved to FileEntries yet. + std::vector TopHeaderNames; + public: /// \brief The headers that are part of this module. SmallVector Headers; @@ -75,9 +82,6 @@ public: /// \brief The headers that are explicitly excluded from this module. SmallVector ExcludedHeaders; - /// \brief The top-level headers associated with this module. - llvm::SmallSetVector TopHeaders; - /// \brief The set of language features required to use this module. /// /// If any of these features is not present, the \c IsAvailable bit @@ -292,6 +296,20 @@ public: return Umbrella && Umbrella.is(); } + /// \brief Add a top-level header associated with this module. + void addTopHeader(const FileEntry *File) { + assert(File); + TopHeaders.insert(File); + } + + /// \brief Add a top-level header filename associated with this module. + void addTopHeaderFilename(StringRef Filename) { + TopHeaderNames.push_back(Filename); + } + + /// \brief The top-level headers associated with this module. + ArrayRef getTopHeaders(FileManager &FileMgr); + /// \brief Add the given feature requirement to the list of features /// required by this module. /// diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 65deac1b4a..f074391098 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" @@ -129,6 +130,19 @@ const DirectoryEntry *Module::getUmbrellaDir() const { return Umbrella.dyn_cast(); } +ArrayRef Module::getTopHeaders(FileManager &FileMgr) { + if (!TopHeaderNames.empty()) { + for (std::vector::iterator + I = TopHeaderNames.begin(), E = TopHeaderNames.end(); I != E; ++I) { + if (const FileEntry *FE = FileMgr.getFile(*I)) + TopHeaders.insert(FE); + } + TopHeaderNames.clear(); + } + + return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end()); +} + void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target) { Requires.push_back(Feature); diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 965e762d79..f3466f0234 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -173,12 +173,12 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, // Add includes for each of these headers. for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) { const FileEntry *Header = Module->Headers[I]; - Module->TopHeaders.insert(Header); + Module->addTopHeader(Header); addHeaderInclude(Header, Includes, LangOpts); } if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { - Module->TopHeaders.insert(UmbrellaHeader); + Module->addTopHeader(UmbrellaHeader); if (Module->Parent) { // Include the umbrella header for submodules. addHeaderInclude(UmbrellaHeader, Includes, LangOpts); @@ -203,7 +203,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, if (const FileEntry *Header = FileMgr.getFile(Dir->path())) { if (ModMap.isHeaderInUnavailableModule(Header)) continue; - Module->TopHeaders.insert(Header); + Module->addTopHeader(Header); } // Include this header umbrella header for submodules. diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 81cb94de51..f9b4e2c947 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -202,7 +202,7 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { llvm::sys::path::stem(File->getName()), NameBuf); Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, Explicit).first; - Result->TopHeaders.insert(File); + Result->addTopHeader(File); // If inferred submodules export everything they import, add a // wildcard to the set of exports. diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 93ae6f1c44..54fe424ddf 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3546,9 +3546,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - // FIXME: Be more lazy about this! - if (const FileEntry *File = PP.getFileManager().getFile(Blob)) - CurrentModule->TopHeaders.insert(File); + CurrentModule->addTopHeaderFilename(Blob); break; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 815cf12f11..8f48d5870a 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2170,11 +2170,13 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record, Mod->ExcludedHeaders[I]->getName()); } - for (unsigned I = 0, N = Mod->TopHeaders.size(); I != N; ++I) { + ArrayRef + TopHeaders = Mod->getTopHeaders(PP->getFileManager()); + for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) { Record.clear(); Record.push_back(SUBMODULE_TOPHEADER); Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, - Mod->TopHeaders[I]->getName()); + TopHeaders[I]->getName()); } // Emit the imports. diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 46d61e995c..88b49edaaf 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1996,12 +1996,12 @@ static int inspect_cursor_at(int argc, const char **argv) { unsigned i, numHeaders; if (mod) { name = clang_Module_getFullName(mod); - numHeaders = clang_Module_getNumTopLevelHeaders(mod); + numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod); printf(" ModuleName=%s Headers(%d):", clang_getCString(name), numHeaders); clang_disposeString(name); for (i = 0; i < numHeaders; ++i) { - CXFile file = clang_Module_getTopLevelHeader(mod, i); + CXFile file = clang_Module_getTopLevelHeader(TU, mod, i); CXString filename = clang_getFileName(file); printf("\n%s", clang_getCString(filename)); clang_disposeString(filename); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index a2449bdc3f..d63f4def29 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -5984,20 +5984,26 @@ CXString clang_Module_getFullName(CXModule CXMod) { return cxstring::createDup(Mod->getFullModuleName()); } -unsigned clang_Module_getNumTopLevelHeaders(CXModule CXMod) { - if (!CXMod) +unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit TU, + CXModule CXMod) { + if (!TU || !CXMod) return 0; Module *Mod = static_cast(CXMod); - return Mod->TopHeaders.size(); + FileManager &FileMgr = cxtu::getASTUnit(TU)->getFileManager(); + ArrayRef TopHeaders = Mod->getTopHeaders(FileMgr); + return TopHeaders.size(); } -CXFile clang_Module_getTopLevelHeader(CXModule CXMod, unsigned Index) { - if (!CXMod) +CXFile clang_Module_getTopLevelHeader(CXTranslationUnit TU, + CXModule CXMod, unsigned Index) { + if (!TU || !CXMod) return 0; Module *Mod = static_cast(CXMod); + FileManager &FileMgr = cxtu::getASTUnit(TU)->getFileManager(); - if (Index < Mod->TopHeaders.size()) - return const_cast(Mod->TopHeaders[Index]); + ArrayRef TopHeaders = Mod->getTopHeaders(FileMgr); + if (Index < TopHeaders.size()) + return const_cast(TopHeaders[Index]); return 0; } -- 2.40.0