diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp | 402 | 
1 files changed, 215 insertions, 187 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp index 93a34b722274..ff041a8ec431 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp @@ -51,12 +51,13 @@  using namespace clang; -CompilerInstance::CompilerInstance(bool BuildingModule) -  : ModuleLoader(BuildingModule), -    Invocation(new CompilerInvocation()), ModuleManager(nullptr), -    BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), -    ModuleBuildFailed(false) { -} +CompilerInstance::CompilerInstance( +    std::shared_ptr<PCHContainerOperations> PCHContainerOps, +    bool BuildingModule) +    : ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()), +      ModuleManager(nullptr), ThePCHContainerOperations(PCHContainerOps), +      BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), +      ModuleBuildFailed(false) {}  CompilerInstance::~CompilerInstance() {    assert(OutputFiles.empty() && "Still output files in flight?"); @@ -321,7 +322,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {                            PP->getFileManager(), PPOpts);    // Predefine macros and configure the preprocessor. -  InitializePreprocessor(*PP, PPOpts, getFrontendOpts()); +  InitializePreprocessor(*PP, PPOpts, *getPCHContainerOperations(), +                         getFrontendOpts());    // Initialize the header search object.    ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(), @@ -329,14 +331,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {    PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP); -  // Set up the module path, including the hash for the -  // module-creation options. -  SmallString<256> SpecificModuleCache( -                           getHeaderSearchOpts().ModuleCachePath); -  if (!getHeaderSearchOpts().DisableModuleHash) -    llvm::sys::path::append(SpecificModuleCache, -                            getInvocation().getModuleHash()); -  PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache); +  if (PP->getLangOpts().Modules) +    PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());    // Handle generating dependencies, if requested.    const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); @@ -371,14 +367,17 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {      AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"",                             /*ShowDepth=*/true, /*MSStyle=*/true);    } +} -  // Load all explictly-specified module map files. -  for (const auto &Filename : getFrontendOpts().ModuleMapFiles) { -    if (auto *File = getFileManager().getFile(Filename)) -      PP->getHeaderSearchInfo().loadModuleMapFile(File, /*IsSystem*/false); -    else -      getDiagnostics().Report(diag::err_module_map_not_found) << Filename; -  } +std::string CompilerInstance::getSpecificModuleCachePath() { +  // Set up the module path, including the hash for the +  // module-creation options. +  SmallString<256> SpecificModuleCache( +                           getHeaderSearchOpts().ModuleCachePath); +  if (!getHeaderSearchOpts().DisableModuleHash) +    llvm::sys::path::append(SpecificModuleCache, +                            getInvocation().getModuleHash()); +  return SpecificModuleCache.str();  }  // ASTContext @@ -396,32 +395,32 @@ void CompilerInstance::createASTContext() {  void CompilerInstance::createPCHExternalASTSource(      StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors,      void *DeserializationListener, bool OwnDeserializationListener) { -  IntrusiveRefCntPtr<ExternalASTSource> Source;    bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; -  Source = createPCHExternalASTSource( +  ModuleManager = createPCHExternalASTSource(        Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,        AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(), -      DeserializationListener, OwnDeserializationListener, Preamble, +      *getPCHContainerOperations(), DeserializationListener, +      OwnDeserializationListener, Preamble,        getFrontendOpts().UseGlobalModuleIndex); -  ModuleManager = static_cast<ASTReader*>(Source.get()); -  getASTContext().setExternalSource(Source);  } -ExternalASTSource *CompilerInstance::createPCHExternalASTSource( -    StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, +IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( +    StringRef Path, StringRef Sysroot, bool DisablePCHValidation,      bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, +    const PCHContainerOperations &PCHContainerOps,      void *DeserializationListener, bool OwnDeserializationListener,      bool Preamble, bool UseGlobalModuleIndex) {    HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); -  std::unique_ptr<ASTReader> Reader; -  Reader.reset(new ASTReader(PP, Context, -                             Sysroot.empty() ? "" : Sysroot.c_str(), -                             DisablePCHValidation, -                             AllowPCHWithCompilerErrors, -                             /*AllowConfigurationMismatch*/false, -                             HSOpts.ModulesValidateSystemHeaders, -                             UseGlobalModuleIndex)); +  IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader( +      PP, Context, PCHContainerOps, Sysroot.empty() ? "" : Sysroot.data(), +      DisablePCHValidation, AllowPCHWithCompilerErrors, +      /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, +      UseGlobalModuleIndex)); + +  // We need the external source to be set up before we read the AST, because +  // eagerly-deserialized declarations may use it. +  Context.setExternalSource(Reader.get());    Reader->setDeserializationListener(        static_cast<ASTDeserializationListener *>(DeserializationListener), @@ -435,7 +434,7 @@ ExternalASTSource *CompilerInstance::createPCHExternalASTSource(      // Set the predefines buffer as suggested by the PCH reader. Typically, the      // predefines buffer will be empty.      PP.setPredefines(Reader->getSuggestedPredefines()); -    return Reader.release(); +    return Reader;    case ASTReader::Failure:      // Unrecoverable failure: don't even try to process the input file. @@ -450,6 +449,7 @@ ExternalASTSource *CompilerInstance::createPCHExternalASTSource(      break;    } +  Context.setExternalSource(nullptr);    return nullptr;  } @@ -497,12 +497,14 @@ void CompilerInstance::createCodeCompletionConsumer() {  }  void CompilerInstance::createFrontendTimer() { -  FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); +  FrontendTimerGroup.reset(new llvm::TimerGroup("Clang front-end time report")); +  FrontendTimer.reset( +      new llvm::Timer("Clang front-end timer", *FrontendTimerGroup));  }  CodeCompleteConsumer *  CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, -                                               const std::string &Filename, +                                               StringRef Filename,                                                 unsigned Line,                                                 unsigned Column,                                                 const CodeCompleteOptions &Opts, @@ -522,42 +524,43 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,  // Output Files -void CompilerInstance::addOutputFile(const OutputFile &OutFile) { +void CompilerInstance::addOutputFile(OutputFile &&OutFile) {    assert(OutFile.OS && "Attempt to add empty stream to output list!"); -  OutputFiles.push_back(OutFile); +  OutputFiles.push_back(std::move(OutFile));  }  void CompilerInstance::clearOutputFiles(bool EraseFiles) { -  for (std::list<OutputFile>::iterator -         it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { -    delete it->OS; -    if (!it->TempFilename.empty()) { +  for (OutputFile &OF : OutputFiles) { +    // Manually close the stream before we rename it. +    OF.OS.reset(); + +    if (!OF.TempFilename.empty()) {        if (EraseFiles) { -        llvm::sys::fs::remove(it->TempFilename); +        llvm::sys::fs::remove(OF.TempFilename);        } else { -        SmallString<128> NewOutFile(it->Filename); +        SmallString<128> NewOutFile(OF.Filename);          // If '-working-directory' was passed, the output filename should be          // relative to that.          FileMgr->FixupRelativePath(NewOutFile);          if (std::error_code ec = -                llvm::sys::fs::rename(it->TempFilename, NewOutFile.str())) { +                llvm::sys::fs::rename(OF.TempFilename, NewOutFile)) {            getDiagnostics().Report(diag::err_unable_to_rename_temp) -            << it->TempFilename << it->Filename << ec.message(); +            << OF.TempFilename << OF.Filename << ec.message(); -          llvm::sys::fs::remove(it->TempFilename); +          llvm::sys::fs::remove(OF.TempFilename);          }        } -    } else if (!it->Filename.empty() && EraseFiles) -      llvm::sys::fs::remove(it->Filename); +    } else if (!OF.Filename.empty() && EraseFiles) +      llvm::sys::fs::remove(OF.Filename);    }    OutputFiles.clear(); +  NonSeekStream.reset();  } -llvm::raw_fd_ostream * -CompilerInstance::createDefaultOutputFile(bool Binary, -                                          StringRef InFile, +raw_pwrite_stream * +CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,                                            StringRef Extension) {    return createOutputFile(getFrontendOpts().OutputFile, Binary,                            /*RemoveFileOnSignal=*/true, InFile, Extension, @@ -565,21 +568,20 @@ CompilerInstance::createDefaultOutputFile(bool Binary,  }  llvm::raw_null_ostream *CompilerInstance::createNullOutputFile() { -  llvm::raw_null_ostream *OS = new llvm::raw_null_ostream(); -  addOutputFile(OutputFile("", "", OS)); -  return OS; +  auto OS = llvm::make_unique<llvm::raw_null_ostream>(); +  llvm::raw_null_ostream *Ret = OS.get(); +  addOutputFile(OutputFile("", "", std::move(OS))); +  return Ret;  } -llvm::raw_fd_ostream * -CompilerInstance::createOutputFile(StringRef OutputPath, -                                   bool Binary, bool RemoveFileOnSignal, -                                   StringRef InFile, -                                   StringRef Extension, -                                   bool UseTemporary, +raw_pwrite_stream * +CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary, +                                   bool RemoveFileOnSignal, StringRef InFile, +                                   StringRef Extension, bool UseTemporary,                                     bool CreateMissingDirectories) {    std::string OutputPathName, TempPathName;    std::error_code EC; -  llvm::raw_fd_ostream *OS = createOutputFile( +  std::unique_ptr<raw_pwrite_stream> OS = createOutputFile(        OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension,        UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);    if (!OS) { @@ -588,15 +590,16 @@ CompilerInstance::createOutputFile(StringRef OutputPath,      return nullptr;    } +  raw_pwrite_stream *Ret = OS.get();    // Add the output file -- but don't try to remove "-", since this means we are    // using stdin.    addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "", -                TempPathName, OS)); +                           TempPathName, std::move(OS))); -  return OS; +  return Ret;  } -llvm::raw_fd_ostream *CompilerInstance::createOutputFile( +std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(      StringRef OutputPath, std::error_code &Error, bool Binary,      bool RemoveFileOnSignal, StringRef InFile, StringRef Extension,      bool UseTemporary, bool CreateMissingDirectories, @@ -646,14 +649,14 @@ llvm::raw_fd_ostream *CompilerInstance::createOutputFile(      TempPath += "-%%%%%%%%";      int fd;      std::error_code EC = -        llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath); +        llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);      if (CreateMissingDirectories &&          EC == llvm::errc::no_such_file_or_directory) {        StringRef Parent = llvm::sys::path::parent_path(OutputPath);        EC = llvm::sys::fs::create_directories(Parent);        if (!EC) { -        EC = llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath); +        EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);        }      } @@ -684,7 +687,13 @@ llvm::raw_fd_ostream *CompilerInstance::createOutputFile(    if (TempPathName)      *TempPathName = TempFile; -  return OS.release(); +  if (!Binary || OS->supportsSeeking()) +    return std::move(OS); + +  auto B = llvm::make_unique<llvm::buffer_ostream>(*OS); +  assert(!NonSeekStream); +  NonSeekStream = std::move(OS); +  return std::move(B);  }  // Initialization Utilities @@ -915,7 +924,8 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,    // Construct a compiler instance that will be used to actually create the    // module. -  CompilerInstance Instance(/*BuildingModule=*/true); +  CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(), +                            /*BuildingModule=*/true);    Instance.setInvocation(&*Invocation);    Instance.createDiagnostics(new ForwardingDiagnosticConsumer( @@ -943,19 +953,20 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,    if (const FileEntry *ModuleMapFile =            ModMap.getContainingModuleMapFile(Module)) {      // Use the module map where this module resides. -    FrontendOpts.Inputs.push_back( -        FrontendInputFile(ModuleMapFile->getName(), IK)); +    FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK);    } else { +    SmallString<128> FakeModuleMapFile(Module->Directory->getName()); +    llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map"); +    FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK); +      llvm::raw_string_ostream OS(InferredModuleMapContent);      Module->print(OS);      OS.flush(); -    FrontendOpts.Inputs.push_back( -        FrontendInputFile("__inferred_module.map", IK));      std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =          llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);      ModuleMapFile = Instance.getFileManager().getVirtualFile( -        "__inferred_module.map", InferredModuleMapContent.size(), 0); +        FakeModuleMapFile, InferredModuleMapContent.size(), 0);      SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer));    } @@ -1031,9 +1042,19 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,      case llvm::LockFileManager::LFS_Shared:        // Someone else is responsible for building the module. Wait for them to        // finish. -      if (Locked.waitForUnlock() == llvm::LockFileManager::Res_OwnerDied) +      switch (Locked.waitForUnlock()) { +      case llvm::LockFileManager::Res_Success: +        ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate; +        break; +      case llvm::LockFileManager::Res_OwnerDied:          continue; // try again to get the lock. -      ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate; +      case llvm::LockFileManager::Res_Timeout: +        Diags.Report(ModuleNameLoc, diag::err_module_lock_timeout) +            << Module->Name; +        // Clear the lock file so that future invokations can make progress. +        Locked.unsafeRemoveLockFile(); +        return false; +      }        break;      } @@ -1071,79 +1092,51 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,    // not have changed.    if (!Id->hadMacroDefinition())      return; +  auto *LatestLocalMD = PP.getLocalMacroDirectiveHistory(Id); -  // If this identifier does not currently have a macro definition, -  // check whether it had one on the command line. -  if (!Id->hasMacroDefinition()) { -    MacroDirective::DefInfo LatestDef = -        PP.getMacroDirectiveHistory(Id)->getDefinition(); -    for (MacroDirective::DefInfo Def = LatestDef; Def; -           Def = Def.getPreviousDefinition()) { -      FileID FID = SourceMgr.getFileID(Def.getLocation()); -      if (FID.isInvalid()) -        continue; - -      // We only care about the predefines buffer. -      if (FID != PP.getPredefinesFileID()) -        continue; - -      // This macro was defined on the command line, then #undef'd later. -      // Complain. -      PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) -        << true << ConfigMacro << Mod->getFullModuleName(); -      if (LatestDef.isUndefined()) -        PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here) -          << true; -      return; -    } - -    // Okay: no definition in the predefines buffer. -    return; -  } - -  // This identifier has a macro definition. Check whether we had a definition -  // on the command line. -  MacroDirective::DefInfo LatestDef = -      PP.getMacroDirectiveHistory(Id)->getDefinition(); -  MacroDirective::DefInfo PredefinedDef; -  for (MacroDirective::DefInfo Def = LatestDef; Def; -         Def = Def.getPreviousDefinition()) { -    FileID FID = SourceMgr.getFileID(Def.getLocation()); -    if (FID.isInvalid()) -      continue; - +  // Find the macro definition from the command line. +  MacroInfo *CmdLineDefinition = nullptr; +  for (auto *MD = LatestLocalMD; MD; MD = MD->getPrevious()) {      // We only care about the predefines buffer. -    if (FID != PP.getPredefinesFileID()) +    FileID FID = SourceMgr.getFileID(MD->getLocation()); +    if (FID.isInvalid() || FID != PP.getPredefinesFileID())        continue; - -    PredefinedDef = Def; +    if (auto *DMD = dyn_cast<DefMacroDirective>(MD)) +      CmdLineDefinition = DMD->getMacroInfo();      break;    } -  // If there was no definition for this macro in the predefines buffer, -  // complain. -  if (!PredefinedDef || -      (!PredefinedDef.getLocation().isValid() && -       PredefinedDef.getUndefLocation().isValid())) { +  auto *CurrentDefinition = PP.getMacroInfo(Id); +  if (CurrentDefinition == CmdLineDefinition) { +    // Macro matches. Nothing to do. +  } else if (!CurrentDefinition) { +    // This macro was defined on the command line, then #undef'd later. +    // Complain. +    PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) +      << true << ConfigMacro << Mod->getFullModuleName(); +    auto LatestDef = LatestLocalMD->getDefinition(); +    assert(LatestDef.isUndefined() && +           "predefined macro went away with no #undef?"); +    PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here) +      << true; +    return; +  } else if (!CmdLineDefinition) { +    // There was no definition for this macro in the predefines buffer, +    // but there was a local definition. Complain.      PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)        << false << ConfigMacro << Mod->getFullModuleName(); -    PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here) +    PP.Diag(CurrentDefinition->getDefinitionLoc(), +            diag::note_module_def_undef_here) +      << false; +  } else if (!CurrentDefinition->isIdenticalTo(*CmdLineDefinition, PP, +                                               /*Syntactically=*/true)) { +    // The macro definitions differ. +    PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) +      << false << ConfigMacro << Mod->getFullModuleName(); +    PP.Diag(CurrentDefinition->getDefinitionLoc(), +            diag::note_module_def_undef_here)        << false; -    return;    } - -  // If the current macro definition is the same as the predefined macro -  // definition, it's okay. -  if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() || -      LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP, -                                              /*Syntactically=*/true)) -    return; - -  // The macro definitions differ. -  PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) -    << false << ConfigMacro << Mod->getFullModuleName(); -  PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here) -    << false;  }  /// \brief Write a new timestamp file with the given path. @@ -1186,8 +1179,7 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {    std::error_code EC;    SmallString<128> ModuleCachePathNative;    llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative); -  for (llvm::sys::fs::directory_iterator -         Dir(ModuleCachePathNative.str(), EC), DirEnd; +  for (llvm::sys::fs::directory_iterator Dir(ModuleCachePathNative, EC), DirEnd;         Dir != DirEnd && !EC; Dir.increment(EC)) {      // If we don't have a directory, there's nothing to look into.      if (!llvm::sys::fs::is_directory(Dir->path())) @@ -1235,9 +1227,10 @@ void CompilerInstance::createModuleManager() {      if (!hasASTContext())        createASTContext(); -    // If we're not recursively building a module, check whether we -    // need to prune the module cache. -    if (getSourceManager().getModuleBuildStack().empty() && +    // If we're implicitly building modules but not currently recursively +    // building a module, check whether we need to prune the module cache. +    if (getLangOpts().ImplicitModules && +        getSourceManager().getModuleBuildStack().empty() &&          getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&          getHeaderSearchOpts().ModuleCachePruneAfter > 0) {        pruneModuleCache(getHeaderSearchOpts()); @@ -1246,13 +1239,18 @@ void CompilerInstance::createModuleManager() {      HeaderSearchOptions &HSOpts = getHeaderSearchOpts();      std::string Sysroot = HSOpts.Sysroot;      const PreprocessorOptions &PPOpts = getPreprocessorOpts(); -    ModuleManager = new ASTReader(getPreprocessor(), *Context, -                                  Sysroot.empty() ? "" : Sysroot.c_str(), -                                  PPOpts.DisablePCHValidation, -                                  /*AllowASTWithCompilerErrors=*/false, -                                  /*AllowConfigurationMismatch=*/false, -                                  HSOpts.ModulesValidateSystemHeaders, -                                  getFrontendOpts().UseGlobalModuleIndex); +    std::unique_ptr<llvm::Timer> ReadTimer; +    if (FrontendTimerGroup) +      ReadTimer = llvm::make_unique<llvm::Timer>("Reading modules", +                                                 *FrontendTimerGroup); +    ModuleManager = new ASTReader( +        getPreprocessor(), *Context, *getPCHContainerOperations(), +        Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, +        /*AllowASTWithCompilerErrors=*/false, +        /*AllowConfigurationMismatch=*/false, +        HSOpts.ModulesValidateSystemHeaders, +        getFrontendOpts().UseGlobalModuleIndex, +        std::move(ReadTimer));      if (hasASTConsumer()) {        ModuleManager->setDeserializationListener(          getASTConsumer().GetASTDeserializationListener()); @@ -1268,12 +1266,18 @@ void CompilerInstance::createModuleManager() {  }  bool CompilerInstance::loadModuleFile(StringRef FileName) { +  llvm::Timer Timer; +  if (FrontendTimerGroup) +    Timer.init("Preloading " + FileName.str(), *FrontendTimerGroup); +  llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); +    // Helper to recursively read the module names for all modules we're adding.    // We mark these as known and redirect any attempt to load that module to    // the files we were handed.    struct ReadModuleNames : ASTReaderListener {      CompilerInstance &CI;      std::vector<StringRef> ModuleFileStack; +    std::vector<StringRef> ModuleNameStack;      bool Failed;      bool TopFileIsModule; @@ -1283,21 +1287,37 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {      bool needsImportVisitation() const override { return true; }      void visitImport(StringRef FileName) override { +      if (!CI.ExplicitlyLoadedModuleFiles.insert(FileName).second) { +        if (ModuleFileStack.size() == 0) +          TopFileIsModule = true; +        return; +      } +        ModuleFileStack.push_back(FileName); +      ModuleNameStack.push_back(StringRef());        if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(), +                                             *CI.getPCHContainerOperations(),                                               *this)) { -        CI.getDiagnostics().Report(SourceLocation(), -                                   diag::err_module_file_not_found) +        CI.getDiagnostics().Report( +            SourceLocation(), CI.getFileManager().getBufferForFile(FileName) +                                  ? diag::err_module_file_invalid +                                  : diag::err_module_file_not_found)              << FileName; -        // FIXME: Produce a note stack explaining how we got here. +        for (int I = ModuleFileStack.size() - 2; I >= 0; --I) +          CI.getDiagnostics().Report(SourceLocation(), +                                     diag::note_module_file_imported_by) +              << ModuleFileStack[I] +              << !ModuleNameStack[I].empty() << ModuleNameStack[I];          Failed = true;        } +      ModuleNameStack.pop_back();        ModuleFileStack.pop_back();      }      void ReadModuleName(StringRef ModuleName) override {        if (ModuleFileStack.size() == 1)          TopFileIsModule = true; +      ModuleNameStack.back() = ModuleName;        auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];        if (!ModuleFile.empty() && @@ -1310,6 +1330,19 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {      }    } RMN(*this); +  // If we don't already have an ASTReader, create one now. +  if (!ModuleManager) +    createModuleManager(); + +  // Tell the module manager about this module file. +  if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) { +    getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found) +      << FileName; +    return false; +  } + +  // Build our mapping of module names to module files from this file +  // and its imports.    RMN.visitImport(FileName);    if (RMN.Failed) @@ -1343,7 +1376,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,      if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule &&          ModuleName != getLangOpts().ImplementationOfModule)        ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility, -                                       ImportLoc, /*Complain=*/false); +                                       ImportLoc);      return LastModuleImportResult;    } @@ -1373,6 +1406,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,      auto Override = ModuleFileOverrides.find(ModuleName);      bool Explicit = Override != ModuleFileOverrides.end(); +    if (!Explicit && !getLangOpts().ImplicitModules) { +      getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled) +          << ModuleName; +      ModuleBuildFailed = true; +      return ModuleLoadResult(); +    }      std::string ModuleFileName =          Explicit ? Override->second @@ -1391,6 +1430,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,      for (auto &Listener : DependencyCollectors)        Listener->attachToASTReader(*ModuleManager); +    llvm::Timer Timer; +    if (FrontendTimerGroup) +      Timer.init("Loading " + ModuleFileName, *FrontendTimerGroup); +    llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); +      // Try to load the module file.      unsigned ARRFlags =          Explicit ? 0 : ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; @@ -1580,8 +1624,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,        return ModuleLoadResult();      } -    ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc, -                                     /*Complain=*/true); +    ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);    }    // Check for any configuration macros that have changed. @@ -1591,25 +1634,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,                       Module, ImportLoc);    } -  // Determine whether we're in the #include buffer for a module. The #includes -  // in that buffer do not qualify as module imports; they're just an -  // implementation detail of us building the module. -  bool IsInModuleIncludes = !getLangOpts().CurrentModule.empty() && -                            getSourceManager().getFileID(ImportLoc) == -                                getSourceManager().getMainFileID(); - -  // If this module import was due to an inclusion directive, create an  -  // implicit import declaration to capture it in the AST. -  if (IsInclusionDirective && hasASTContext() && !IsInModuleIncludes) { -    TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); -    ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, -                                                     ImportLoc, Module, -                                                     Path.back().second); -    TU->addDecl(ImportD); -    if (Consumer) -      Consumer->HandleImplicitImportDecl(ImportD); -  } -      LastModuleImportLoc = ImportLoc;    LastModuleImportResult = ModuleLoadResult(Module, false);    return LastModuleImportResult; @@ -1617,9 +1641,13 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,  void CompilerInstance::makeModuleVisible(Module *Mod,                                           Module::NameVisibilityKind Visibility, -                                         SourceLocation ImportLoc, -                                         bool Complain){ -  ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain); +                                         SourceLocation ImportLoc) { +  if (!ModuleManager) +    createModuleManager(); +  if (!ModuleManager) +    return; + +  ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc);  }  GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( @@ -1639,8 +1667,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(      llvm::sys::fs::create_directories(        getPreprocessor().getHeaderSearchInfo().getModuleCachePath());      GlobalModuleIndex::writeIndex( -      getFileManager(), -      getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); +        getFileManager(), *getPCHContainerOperations(), +        getPreprocessor().getHeaderSearchInfo().getModuleCachePath());      ModuleManager->resetForReload();      ModuleManager->loadGlobalIndex();      GlobalIndex = ModuleManager->getGlobalIndex(); @@ -1667,8 +1695,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(      }      if (RecreateIndex) {        GlobalModuleIndex::writeIndex( -        getFileManager(), -        getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); +          getFileManager(), *getPCHContainerOperations(), +          getPreprocessor().getHeaderSearchInfo().getModuleCachePath());        ModuleManager->resetForReload();        ModuleManager->loadGlobalIndex();        GlobalIndex = ModuleManager->getGlobalIndex();  | 
