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"  | 

