From: Douglas Gregor Date: Thu, 8 Dec 2011 17:01:29 +0000 (+0000) Subject: Keep track of import dependencies between submodules within the module X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5e3f9223db88227d6d21679c613b139d8160186d;p=clang Keep track of import dependencies between submodules within the module that's currently being built. This is important for supporting transitive dependencies ("export *" in the module map) completely. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146156 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index 47fb7d28e4..148f599cc3 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -142,15 +142,12 @@ public: /// SearchPath at which the file was found. This only differs from the /// Filename for framework includes. /// - /// \param BuildingModule The name of the module we're currently building. - /// /// \param SuggestedModule If non-null, and the file found is semantically /// part of a known module, this will be set to the module that should /// be imported instead of preprocessing/parsing the file found. const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, - StringRef BuildingModule, Module **SuggestedModule) const; private: @@ -158,7 +155,6 @@ private: StringRef Filename, HeaderSearch &HS, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, - StringRef BuildingModule, Module **SuggestedModule) const; }; diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index fba3606f44..02f8c02120 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -135,9 +135,6 @@ class HeaderSearch { /// \brief The path to the module cache. std::string ModuleCachePath; - /// \brief The name of the module we're building. - std::string BuildingModule; - /// FileInfo - This contains all of the preprocessor-specific data about files /// that are included. The vector is indexed by the FileEntry's UID. /// @@ -216,11 +213,9 @@ public: SystemDirIdx++; } - /// \brief Set the path to the module cache and the name of the module - /// we're building - void configureModules(StringRef CachePath, StringRef BuildingModule) { + /// \brief Set the path to the module cache. + void setModuleCachePath(StringRef CachePath) { ModuleCachePath = CachePath; - this->BuildingModule = BuildingModule; } /// \brief Retrieve the path to the module cache. diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 4463fa7f2c..84df382e27 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -278,8 +278,7 @@ void CompilerInstance::createPreprocessor() { if (!getHeaderSearchOpts().DisableModuleHash) llvm::sys::path::append(SpecificModuleCache, getInvocation().getModuleHash()); - PP->getHeaderSearchInfo().configureModules(SpecificModuleCache, - getLangOpts().CurrentModule); + PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache); // Handle generating dependencies, if requested. const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); @@ -1105,7 +1104,14 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, // If we don't already have information on this module, load the module now. llvm::DenseMap::iterator Known = KnownModules.find(Path[0].first); - if (Known == KnownModules.end()) { + if (Known != KnownModules.end()) { + // Retrieve the cached top-level module. + Module = Known->second; + } else if (ModuleName == getLangOpts().CurrentModule) { + // This is the module we're building. + Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName); + Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; + } else { // Search for a module with the given name. std::string ModuleFileName; ModuleFile @@ -1204,9 +1210,6 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, // Cache the result of this top-level module lookup for later. Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; - } else { - // Retrieve the cached top-level module. - Module = Known->second; } // If we never found the module, fail. @@ -1265,8 +1268,10 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, } } - // Make the named module visible. - ModuleManager->makeModuleVisible(Module, Visibility); + // Make the named module visible, if it's not already part of the module + // we are parsing. + if (ModuleName != getLangOpts().CurrentModule) + ModuleManager->makeModuleVisible(Module, Visibility); // If this module import was due to an inclusion directive, create an // implicit import declaration to capture it in the AST. diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 9a7230c24e..b0668c53a4 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -197,7 +197,6 @@ const FileEntry *DirectoryLookup::LookupFile( HeaderSearch &HS, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, - StringRef BuildingModule, Module **SuggestedModule) const { llvm::SmallString<1024> TmpDir; if (isNormalDir()) { @@ -224,10 +223,7 @@ const FileEntry *DirectoryLookup::LookupFile( // If there is a module that corresponds to this header, // suggest it. - Module *Module = HS.findModuleForHeader(File); - if (Module && Module->getTopLevelModuleName() != BuildingModule) - *SuggestedModule = Module; - + *SuggestedModule = HS.findModuleForHeader(File); return File; } @@ -236,7 +232,7 @@ const FileEntry *DirectoryLookup::LookupFile( if (isFramework()) return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, - BuildingModule, SuggestedModule); + SuggestedModule); assert(isHeaderMap() && "Unknown directory lookup"); const FileEntry * const Result = getHeaderMap()->LookupFile( @@ -263,7 +259,6 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( HeaderSearch &HS, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, - StringRef BuildingModule, Module **SuggestedModule) const { FileManager &FileMgr = HS.getFileMgr(); @@ -322,11 +317,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( Module *Module = 0; if (SuggestedModule) { if (const DirectoryEntry *FrameworkDir - = FileMgr.getDirectory(FrameworkName)) { - if ((Module = HS.getFrameworkModule(ModuleName, FrameworkDir)) && - Module->Name == BuildingModule) - Module = 0; - } + = FileMgr.getDirectory(FrameworkName)) + Module = HS.getFrameworkModule(ModuleName, FrameworkDir); } // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" @@ -475,7 +467,7 @@ const FileEntry *HeaderSearch::LookupFile( for (; i != SearchDirs.size(); ++i) { const FileEntry *FE = SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, - BuildingModule, SuggestedModule); + SuggestedModule); if (!FE) continue; CurDir = &SearchDirs[i]; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index b44a0a2934..ba65c29e69 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1352,12 +1352,21 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, break; } - CharSourceRange ReplaceRange(SourceRange(HashLoc, CharEnd), - /*IsTokenRange=*/false); - Diag(HashLoc, diag::warn_auto_module_import) - << IncludeKind << PathString - << FixItHint::CreateReplacement(ReplaceRange, - "__import_module__ " + PathString.str().str() + ";"); + // Determine whether we are actually building the module that this + // include directive maps to. + bool BuildingImportedModule + = Path[0].first->getName() == getLangOptions().CurrentModule; + + if (!BuildingImportedModule) { + // If we're not building the imported module, warn that we're going + // to automatically turn this inclusion directive into a module import. + CharSourceRange ReplaceRange(SourceRange(HashLoc, CharEnd), + /*IsTokenRange=*/false); + Diag(HashLoc, diag::warn_auto_module_import) + << IncludeKind << PathString + << FixItHint::CreateReplacement(ReplaceRange, + "__import_module__ " + PathString.str().str() + ";"); + } // Load the module. // If this was an #__include_macros directive, only make macros visible. @@ -1365,7 +1374,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, = (IncludeKind == 3)? Module::MacrosVisible : Module::AllVisible; TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility, /*IsIncludeDirective=*/true); - return; + + // If this header isn't part of the module we're building, we're done. + if (!BuildingImportedModule) + return; } // The #included file will be considered to be a system header if either it is diff --git a/test/Modules/Inputs/Module.framework/Headers/Sub.h b/test/Modules/Inputs/Module.framework/Headers/Sub.h index 64be702fdc..dea76e7646 100644 --- a/test/Modules/Inputs/Module.framework/Headers/Sub.h +++ b/test/Modules/Inputs/Module.framework/Headers/Sub.h @@ -1,2 +1,3 @@ +#include int *Module_Sub; diff --git a/test/Modules/Inputs/Module.framework/Headers/Sub2.h b/test/Modules/Inputs/Module.framework/Headers/Sub2.h new file mode 100644 index 0000000000..beed4a862d --- /dev/null +++ b/test/Modules/Inputs/Module.framework/Headers/Sub2.h @@ -0,0 +1 @@ +int *Module_Sub2; diff --git a/test/Modules/submodules.m b/test/Modules/submodules.m new file mode 100644 index 0000000000..e5a050f0f4 --- /dev/null +++ b/test/Modules/submodules.m @@ -0,0 +1,11 @@ + +// RUN: rm -rf %t +// RUN: %clang_cc1 -Wauto-import -fmodule-cache-path %t -fauto-module-import -F %S/Inputs %s -verify + +// Note: transitively imports Module.Sub2. +__import_module__ Module.Sub; + +int getValue() { + return *Module_Sub + *Module_Sub2; +} +