diff options
-rw-r--r-- | clang/include/clang/Lex/ModuleMap.h | 11 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 72 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 9 | ||||
-rw-r--r-- | clang/test/Modules/normal-module-map.cpp | 4 |
4 files changed, 83 insertions, 13 deletions
diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index d38bbe672bd..4f89f1e7288 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -166,7 +166,16 @@ public: /// framework directory. Module *inferFrameworkModule(StringRef ModuleName, const DirectoryEntry *FrameworkDir); - + + /// \brief Retrieve the module map file containing the definition of the given + /// module. + /// + /// \param Module The module whose module map file will be returned, if known. + /// + /// \returns The file entry for the module map file containing the given + /// module, or NULL if the module definition was inferred. + const FileEntry *getContainingModuleMapFile(ModuleMap::Module *Module); + /// \brief Parse the given module map file, and record any modules we /// encounter. /// diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index c6a55839848..433b2cceb7d 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -710,6 +710,21 @@ static void doCompileModule(void *UserData) { } namespace { + struct CompileModuleMapData { + CompilerInstance &Instance; + GenerateModuleAction &CreateModuleAction; + }; +} + +/// \brief Helper function that executes the module-generating action under +/// a crash recovery context. +static void doCompileMapModule(void *UserData) { + CompileModuleMapData &Data + = *reinterpret_cast<CompileModuleMapData *>(UserData); + Data.Instance.ExecuteAction(Data.CreateModuleAction); +} + +namespace { /// \brief Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// @@ -958,17 +973,11 @@ void LockFileManager::waitForUnlock() { // Give up. } -/// \brief Compile a module file for the given module name with the given -/// umbrella header, using the options provided by the importing compiler -/// instance. +/// \brief Compile a module file for the given module, using the options +/// provided by the importing compiler instance. static void compileModule(CompilerInstance &ImportingInstance, ModuleMap::Module *Module, StringRef ModuleFileName) { - // FIXME: Currently, we can only handle modules that have an umbrella - // header. That's lame. - if (!Module->UmbrellaHeader) - return; - LockFileManager Locked(ModuleFileName); switch (Locked) { case LockFileManager::LFS_Error: @@ -985,6 +994,9 @@ static void compileModule(CompilerInstance &ImportingInstance, break; } + ModuleMap &ModMap + = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + // Construct a compiler invocation for creating this module. llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation (new CompilerInvocation(ImportingInstance.getInvocation())); @@ -1002,6 +1014,50 @@ static void compileModule(CompilerInstance &ImportingInstance, Invocation->getPreprocessorOpts().ModuleBuildPath .push_back(Module->getTopLevelModuleName()); + if (const FileEntry *ModuleMapFile + = ModMap.getContainingModuleMapFile(Module)) { + // If there is a module map file, build the module using the module map. + // Set up the inputs/outputs so that we build the module from its umbrella + // header. + FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); + FrontendOpts.OutputFile = ModuleFileName.str(); + FrontendOpts.DisableFree = false; + FrontendOpts.Inputs.clear(); + FrontendOpts.Inputs.push_back( + std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()), + ModuleMapFile->getName())); + + Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; + + + assert(ImportingInstance.getInvocation().getModuleHash() == + Invocation->getModuleHash() && "Module hash mismatch!"); + + // Construct a compiler instance that will be used to actually create the + // module. + CompilerInstance Instance; + Instance.setInvocation(&*Invocation); + Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, + &ImportingInstance.getDiagnosticClient(), + /*ShouldOwnClient=*/true, + /*ShouldCloneClient=*/true); + + // Construct a module-generating action. + GenerateModuleAction CreateModuleAction; + + // Execute the action to actually build the module in-place. Use a separate + // thread so that we get a stack large enough. + const unsigned ThreadStackSize = 8 << 20; + llvm::CrashRecoveryContext CRC; + CompileModuleMapData Data = { Instance, CreateModuleAction }; + CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); + return; + } + + // FIXME: Temporary fallback: generate the module from the umbrella header. + // This is currently used when we infer a module map from a framework. + assert(Module->UmbrellaHeader && "Inferred module map needs umbrella header"); + // Set up the inputs/outputs so that we build the module from its umbrella // header. FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index a25c93bfca4..3cc6478acf6 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -206,6 +206,15 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, return Result; } +const FileEntry * +ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) { + if (Module->DefinitionLoc.isInvalid() || !SourceMgr) + return 0; + + return SourceMgr->getFileEntryForID( + SourceMgr->getFileID(Module->DefinitionLoc)); +} + void ModuleMap::dump() { llvm::errs() << "Modules:"; for (llvm::StringMap<Module *>::iterator M = Modules.begin(), diff --git a/clang/test/Modules/normal-module-map.cpp b/clang/test/Modules/normal-module-map.cpp index c87657f5a9b..19294950d49 100644 --- a/clang/test/Modules/normal-module-map.cpp +++ b/clang/test/Modules/normal-module-map.cpp @@ -1,8 +1,4 @@ // RUN: rm -rf %t -// FIXME: Eventually, we should be able to remove these explicit module creation lines -// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libA -emit-module-from-map %S/Inputs/normal-module-map/module.map -// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libB -emit-module-from-map %S/Inputs/normal-module-map/module.map -// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libNested -emit-module-from-map %S/Inputs/normal-module-map/nested/module.map // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify #include "Umbrella/umbrella_sub.h" |