diff options
Diffstat (limited to 'lib/Frontend/CompilerInstance.cpp')
| -rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 268 | 
1 files changed, 185 insertions, 83 deletions
| diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 6af920d9fd78..93a34b722274 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -101,14 +101,18 @@ void CompilerInstance::setSema(Sema *S) {    TheSema.reset(S);  } -void CompilerInstance::setASTConsumer(ASTConsumer *Value) { -  Consumer.reset(Value); +void CompilerInstance::setASTConsumer(std::unique_ptr<ASTConsumer> Value) { +  Consumer = std::move(Value);  }  void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {    CompletionConsumer.reset(Value);  } -  + +std::unique_ptr<Sema> CompilerInstance::takeSema() { +  return std::move(TheSema); +} +  IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const {    return ModuleManager;  } @@ -130,52 +134,48 @@ void CompilerInstance::setModuleDepCollector(  static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,                                 const CodeGenOptions *CodeGenOpts,                                 DiagnosticsEngine &Diags) { -  std::string ErrorInfo; -  bool OwnsStream = false; +  std::error_code EC; +  std::unique_ptr<raw_ostream> StreamOwner;    raw_ostream *OS = &llvm::errs();    if (DiagOpts->DiagnosticLogFile != "-") {      // Create the output stream. -    llvm::raw_fd_ostream *FileOS(new llvm::raw_fd_ostream( -        DiagOpts->DiagnosticLogFile.c_str(), ErrorInfo, -        llvm::sys::fs::F_Append | llvm::sys::fs::F_Text)); -    if (!ErrorInfo.empty()) { +    auto FileOS = llvm::make_unique<llvm::raw_fd_ostream>( +        DiagOpts->DiagnosticLogFile, EC, +        llvm::sys::fs::F_Append | llvm::sys::fs::F_Text); +    if (EC) {        Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) -        << DiagOpts->DiagnosticLogFile << ErrorInfo; +          << DiagOpts->DiagnosticLogFile << EC.message();      } else {        FileOS->SetUnbuffered();        FileOS->SetUseAtomicWrites(true); -      OS = FileOS; -      OwnsStream = true; +      OS = FileOS.get(); +      StreamOwner = std::move(FileOS);      }    }    // Chain in the diagnostic client which will log the diagnostics. -  LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts, -                                                          OwnsStream); +  auto Logger = llvm::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts, +                                                        std::move(StreamOwner));    if (CodeGenOpts)      Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); -  Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); +  assert(Diags.ownsClient()); +  Diags.setClient( +      new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger)));  }  static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts,                                         DiagnosticsEngine &Diags,                                         StringRef OutputFile) { -  std::string ErrorInfo; -  std::unique_ptr<llvm::raw_fd_ostream> OS; -  OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo, -                                    llvm::sys::fs::F_None)); +  auto SerializedConsumer = +      clang::serialized_diags::create(OutputFile, DiagOpts); -  if (!ErrorInfo.empty()) { -    Diags.Report(diag::warn_fe_serialized_diag_failure) -      << OutputFile << ErrorInfo; -    return; +  if (Diags.ownsClient()) { +    Diags.setClient(new ChainedDiagnosticConsumer( +        Diags.takeClient(), std::move(SerializedConsumer))); +  } else { +    Diags.setClient(new ChainedDiagnosticConsumer( +        Diags.getClient(), std::move(SerializedConsumer)));    } - -  DiagnosticConsumer *SerializedConsumer = -      clang::serialized_diags::create(OS.release(), DiagOpts); - -  Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), -                                                SerializedConsumer));  }  void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client, @@ -371,6 +371,14 @@ 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; +  }  }  // ASTContext @@ -569,17 +577,14 @@ CompilerInstance::createOutputFile(StringRef OutputPath,                                     StringRef Extension,                                     bool UseTemporary,                                     bool CreateMissingDirectories) { -  std::string Error, OutputPathName, TempPathName; -  llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, -                                              RemoveFileOnSignal, -                                              InFile, Extension, -                                              UseTemporary, -                                              CreateMissingDirectories, -                                              &OutputPathName, -                                              &TempPathName); +  std::string OutputPathName, TempPathName; +  std::error_code EC; +  llvm::raw_fd_ostream *OS = createOutputFile( +      OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension, +      UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);    if (!OS) { -    getDiagnostics().Report(diag::err_fe_unable_to_open_output) -      << OutputPath << Error; +    getDiagnostics().Report(diag::err_fe_unable_to_open_output) << OutputPath +                                                                << EC.message();      return nullptr;    } @@ -591,17 +596,11 @@ CompilerInstance::createOutputFile(StringRef OutputPath,    return OS;  } -llvm::raw_fd_ostream * -CompilerInstance::createOutputFile(StringRef OutputPath, -                                   std::string &Error, -                                   bool Binary, -                                   bool RemoveFileOnSignal, -                                   StringRef InFile, -                                   StringRef Extension, -                                   bool UseTemporary, -                                   bool CreateMissingDirectories, -                                   std::string *ResultPathName, -                                   std::string *TempPathName) { +llvm::raw_fd_ostream *CompilerInstance::createOutputFile( +    StringRef OutputPath, std::error_code &Error, bool Binary, +    bool RemoveFileOnSignal, StringRef InFile, StringRef Extension, +    bool UseTemporary, bool CreateMissingDirectories, +    std::string *ResultPathName, std::string *TempPathName) {    assert((!CreateMissingDirectories || UseTemporary) &&           "CreateMissingDirectories is only allowed when using temporary files"); @@ -670,9 +669,9 @@ CompilerInstance::createOutputFile(StringRef OutputPath,    if (!OS) {      OSFile = OutFile;      OS.reset(new llvm::raw_fd_ostream( -        OSFile.c_str(), Error, +        OSFile, Error,          (Binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text))); -    if (!Error.empty()) +    if (Error)        return nullptr;    } @@ -705,7 +704,8 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,      Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;    if (Input.isBuffer()) { -    SourceMgr.setMainFileID(SourceMgr.createFileID(Input.getBuffer(), Kind)); +    SourceMgr.setMainFileID(SourceMgr.createFileID( +        std::unique_ptr<llvm::MemoryBuffer>(Input.getBuffer()), Kind));      assert(!SourceMgr.getMainFileID().isInvalid() &&             "Couldn't establish MainFileID!");      return true; @@ -727,14 +727,14 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,      // pick up the correct size, and simply override their contents as we do for      // STDIN.      if (File->isNamedPipe()) { -      std::string ErrorStr; -      if (llvm::MemoryBuffer *MB = -              FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)) { +      auto MB = FileMgr.getBufferForFile(File, /*isVolatile=*/true); +      if (MB) {          // Create a new virtual file that will have the correct size. -        File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0); -        SourceMgr.overrideFileContents(File, MB); +        File = FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0); +        SourceMgr.overrideFileContents(File, std::move(*MB));        } else { -        Diags.Report(diag::err_cannot_open_file) << InputFile << ErrorStr; +        Diags.Report(diag::err_cannot_open_file) << InputFile +                                                 << MB.getError().message();          return false;        }      } @@ -754,7 +754,7 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,                                                     SB->getBufferSize(), 0);      SourceMgr.setMainFileID(          SourceMgr.createFileID(File, SourceLocation(), Kind)); -    SourceMgr.overrideFileContents(File, SB.release()); +    SourceMgr.overrideFileContents(File, std::move(SB));    }    assert(!SourceMgr.getMainFileID().isInvalid() && @@ -802,8 +802,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {      llvm::EnableStatistics();    for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { -    // Reset the ID tables if we are reusing the SourceManager. -    if (hasSourceManager()) +    // Reset the ID tables if we are reusing the SourceManager and parsing +    // regular files. +    if (hasSourceManager() && !Act.isModelParsingAction())        getSourceManager().clearIDTables();      if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) { @@ -951,17 +952,22 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,      FrontendOpts.Inputs.push_back(          FrontendInputFile("__inferred_module.map", IK)); -    llvm::MemoryBuffer *ModuleMapBuffer = +    std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =          llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);      ModuleMapFile = Instance.getFileManager().getVirtualFile(          "__inferred_module.map", InferredModuleMapContent.size(), 0); -    SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer); +    SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer));    } -  // Construct a module-generating action. Passing through Module->ModuleMap is +  // Construct a module-generating action. Passing through the module map is    // safe because the FileManager is shared between the compiler instances. -  GenerateModuleAction CreateModuleAction(Module->ModuleMap, Module->IsSystem); -   +  GenerateModuleAction CreateModuleAction( +      ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem); + +  ImportingInstance.getDiagnostics().Report(ImportLoc, +                                            diag::remark_module_build) +    << Module->Name << ModuleFileName; +    // 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; @@ -969,6 +975,10 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,    CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(CreateModuleAction); },                          ThreadStackSize); +  ImportingInstance.getDiagnostics().Report(ImportLoc, +                                            diag::remark_module_build_done) +    << Module->Name; +    // Delete the temporary module map file.    // FIXME: Even though we're executing under crash protection, it would still    // be nice to do this with RemoveFileOnSignal when we can. However, that @@ -988,9 +998,10 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,                                   SourceLocation ImportLoc,                                   SourceLocation ModuleNameLoc, Module *Module,                                   StringRef ModuleFileName) { +  DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics(); +    auto diagnoseBuildFailure = [&] { -    ImportingInstance.getDiagnostics().Report(ModuleNameLoc, -                                              diag::err_module_not_built) +    Diags.Report(ModuleNameLoc, diag::err_module_not_built)          << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);    }; @@ -1004,6 +1015,8 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,      llvm::LockFileManager Locked(ModuleFileName);      switch (Locked) {      case llvm::LockFileManager::LFS_Error: +      Diags.Report(ModuleNameLoc, diag::err_module_lock_failure) +          << Module->Name;        return false;      case llvm::LockFileManager::LFS_Owned: @@ -1027,7 +1040,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,      // Try to read the module file, now that we've compiled it.      ASTReader::ASTReadResult ReadResult =          ImportingInstance.getModuleManager()->ReadAST( -            ModuleFileName, serialization::MK_Module, ImportLoc, +            ModuleFileName, serialization::MK_ImplicitModule, ImportLoc,              ModuleLoadCapabilities);      if (ReadResult == ASTReader::OutOfDate && @@ -1038,6 +1051,10 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,        continue;      } else if (ReadResult == ASTReader::Missing) {        diagnoseBuildFailure(); +    } else if (ReadResult != ASTReader::Success && +               !Diags.hasErrorOccurred()) { +      // The ASTReader didn't diagnose the error, so conservatively report it. +      diagnoseBuildFailure();      }      return ReadResult == ASTReader::Success;    } @@ -1131,9 +1148,8 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,  /// \brief Write a new timestamp file with the given path.  static void writeTimestampFile(StringRef TimestampFile) { -  std::string ErrorInfo; -  llvm::raw_fd_ostream Out(TimestampFile.str().c_str(), ErrorInfo, -                           llvm::sys::fs::F_None); +  std::error_code EC; +  llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None);  }  /// \brief Prune the module cache of modules that haven't been accessed in @@ -1251,6 +1267,65 @@ void CompilerInstance::createModuleManager() {    }  } +bool CompilerInstance::loadModuleFile(StringRef FileName) { +  // 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; +    bool Failed; +    bool TopFileIsModule; + +    ReadModuleNames(CompilerInstance &CI) +        : CI(CI), Failed(false), TopFileIsModule(false) {} + +    bool needsImportVisitation() const override { return true; } + +    void visitImport(StringRef FileName) override { +      ModuleFileStack.push_back(FileName); +      if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(), +                                             *this)) { +        CI.getDiagnostics().Report(SourceLocation(), +                                   diag::err_module_file_not_found) +            << FileName; +        // FIXME: Produce a note stack explaining how we got here. +        Failed = true; +      } +      ModuleFileStack.pop_back(); +    } + +    void ReadModuleName(StringRef ModuleName) override { +      if (ModuleFileStack.size() == 1) +        TopFileIsModule = true; + +      auto &ModuleFile = CI.ModuleFileOverrides[ModuleName]; +      if (!ModuleFile.empty() && +          CI.getFileManager().getFile(ModuleFile) != +              CI.getFileManager().getFile(ModuleFileStack.back())) +        CI.getDiagnostics().Report(SourceLocation(), +                                   diag::err_conflicting_module_files) +            << ModuleName << ModuleFile << ModuleFileStack.back(); +      ModuleFile = ModuleFileStack.back(); +    } +  } RMN(*this); + +  RMN.visitImport(FileName); + +  if (RMN.Failed) +    return false; + +  // If we never found a module name for the top file, then it's not a module, +  // it's a PCH or preamble or something. +  if (!RMN.TopFileIsModule) { +    getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_module) +      << FileName; +    return false; +  } + +  return true; +} +  ModuleLoadResult  CompilerInstance::loadModule(SourceLocation ImportLoc,                               ModuleIdPath Path, @@ -1265,7 +1340,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,    // when both the preprocessor and parser see the same import declaration.    if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) {      // Make the named module visible. -    if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule) +    if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule && +        ModuleName != getLangOpts().ImplementationOfModule)        ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,                                         ImportLoc, /*Complain=*/false);      return LastModuleImportResult; @@ -1279,7 +1355,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,    if (Known != KnownModules.end()) {      // Retrieve the cached top-level module.      Module = Known->second;     -  } else if (ModuleName == getLangOpts().CurrentModule) { +  } else if (ModuleName == getLangOpts().CurrentModule || +             ModuleName == getLangOpts().ImplementationOfModule) {      // This is the module we're building.       Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);      Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; @@ -1294,8 +1371,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,        return ModuleLoadResult();      } +    auto Override = ModuleFileOverrides.find(ModuleName); +    bool Explicit = Override != ModuleFileOverrides.end(); +      std::string ModuleFileName = -        PP->getHeaderSearchInfo().getModuleFileName(Module); +        Explicit ? Override->second +                 : PP->getHeaderSearchInfo().getModuleFileName(Module);      // If we don't already have an ASTReader, create one now.      if (!ModuleManager) @@ -1311,14 +1392,24 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,        Listener->attachToASTReader(*ModuleManager);      // Try to load the module file. -    unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; -    switch (ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module, +    unsigned ARRFlags = +        Explicit ? 0 : ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; +    switch (ModuleManager->ReadAST(ModuleFileName, +                                   Explicit ? serialization::MK_ExplicitModule +                                            : serialization::MK_ImplicitModule,                                     ImportLoc, ARRFlags)) {      case ASTReader::Success:        break;      case ASTReader::OutOfDate:      case ASTReader::Missing: { +      if (Explicit) { +        // ReadAST has already complained for us. +        ModuleLoader::HadFatalFailure = true; +        KnownModules[Path[0].first] = nullptr; +        return ModuleLoadResult(); +      } +        // The module file is missing or out-of-date. Build it.        assert(Module && "missing module file");        // Check whether there is a cycle in the module graph. @@ -1342,9 +1433,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,          return ModuleLoadResult();        } -      getDiagnostics().Report(ImportLoc, diag::remark_module_build) -          << ModuleName << ModuleFileName; -        // Check whether we have already attempted to build this module (but        // failed).        if (getPreprocessorOpts().FailedModules && @@ -1359,6 +1447,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,        // Try to compile and then load the module.        if (!compileAndLoadModule(*this, ImportLoc, ModuleNameLoc, Module,                                  ModuleFileName)) { +        assert(getDiagnostics().hasErrorOccurred() && +               "undiagnosed error in compileAndLoadModule");          if (getPreprocessorOpts().FailedModules)            getPreprocessorOpts().FailedModules->addFailed(ModuleName);          KnownModules[Path[0].first] = nullptr; @@ -1448,6 +1538,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,        Module = Sub;      }    } + +  // Don't make the module visible if we are in the implementation. +  if (ModuleName == getLangOpts().ImplementationOfModule) +    return ModuleLoadResult(Module, false);    // Make the named module visible, if it's not already part of the module    // we are parsing. @@ -1468,7 +1562,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,      // Check whether this module is available.      clang::Module::Requirement Requirement; -    clang::Module::HeaderDirective MissingHeader; +    clang::Module::UnresolvedHeaderDirective MissingHeader;      if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement,                               MissingHeader)) {        if (MissingHeader.FileNameLoc.isValid()) { @@ -1497,9 +1591,16 @@ 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()) { +  if (IsInclusionDirective && hasASTContext() && !IsInModuleIncludes) {      TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();      ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,                                                       ImportLoc, Module, @@ -1602,3 +1703,4 @@ CompilerInstance::lookupMissingImports(StringRef Name,    return false;  } +void CompilerInstance::resetAndLeakSema() { BuryPointer(takeSema()); } | 
