diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 99 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 103 |
3 files changed, 116 insertions, 93 deletions
diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index e09b2857a37..d0e857be3ca 100644 --- a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -58,7 +58,7 @@ public: const std::string &OutputFileName, raw_pwrite_stream *OS, std::shared_ptr<PCHBuffer> Buffer) - : Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), + : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), TargetOpts(TO), LangOpts(LO), OS(OS), Buffer(Buffer) { // The debug info output isn't affected by CodeModel and // ThreadModel, but the backend expects them to be nonempty. @@ -71,6 +71,11 @@ public: virtual ~PCHContainerGenerator() {} void Initialize(ASTContext &Context) override { + if (Ctx) { + assert(Ctx == &Context); + return; + } + Ctx = &Context; VMContext.reset(new llvm::LLVMContext()); M.reset(new llvm::Module(MainFileName, *VMContext)); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 5133ffc2726..7d9efd4e9be 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1261,8 +1261,10 @@ void CompilerInstance::createModuleManager() { getASTContext().setExternalSource(ModuleManager); if (hasSema()) ModuleManager->InitializeSema(getSema()); - if (hasASTConsumer()) + if (hasASTConsumer()) { + getASTConsumer().Initialize(getASTContext()); ModuleManager->StartTranslationUnit(&getASTConsumer()); + } if (TheDependencyFileGenerator) TheDependencyFileGenerator->AttachToASTReader(*ModuleManager); @@ -1284,86 +1286,44 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { // the files we were handed. struct ReadModuleNames : ASTReaderListener { CompilerInstance &CI; - std::vector<StringRef> ModuleFileStack; - std::vector<StringRef> ModuleNameStack; - bool Failed; - bool TopFileIsModule; - - ReadModuleNames(CompilerInstance &CI) - : CI(CI), Failed(false), TopFileIsModule(false) {} - - bool needsImportVisitation() const override { return true; } + llvm::SmallVector<IdentifierInfo*, 8> LoadedModules; - void visitImport(StringRef FileName) override { - if (!CI.ExplicitlyLoadedModuleFiles.insert(FileName).second) { - if (ModuleFileStack.size() == 0) - TopFileIsModule = true; - return; - } + ReadModuleNames(CompilerInstance &CI) : CI(CI) {} - ModuleFileStack.push_back(FileName); - ModuleNameStack.push_back(StringRef()); - if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(), - CI.getPCHContainerReader(), - *this)) { - CI.getDiagnostics().Report( - SourceLocation(), CI.getFileManager().getBufferForFile(FileName) - ? diag::err_module_file_invalid - : diag::err_module_file_not_found) - << FileName; - 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 { + LoadedModules.push_back( + CI.getPreprocessor().getIdentifierInfo(ModuleName)); } - void ReadModuleName(StringRef ModuleName) override { - if (ModuleFileStack.size() == 1) - TopFileIsModule = true; - ModuleNameStack.back() = ModuleName; - - 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(); + void registerAll() { + for (auto *II : LoadedModules) { + CI.KnownModules[II] = CI.getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .findModule(II->getName()); + } + LoadedModules.clear(); } - } 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) - return false; + auto Listener = llvm::make_unique<ReadModuleNames>(*this); + auto &ListenerRef = *Listener; + ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager, + std::move(Listener)); - // 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; + // Try to load the module file. + if (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule, + SourceLocation(), ASTReader::ARR_None) + != ASTReader::Success) return false; - } + // We successfully loaded the module file; remember the set of provided + // modules so that we don't try to load implicit modules for them. + ListenerRef.registerAll(); return true; } @@ -1412,6 +1372,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return ModuleLoadResult(); } + // FIXME: Rmove ModuleFileOverrides auto Override = ModuleFileOverrides.find(ModuleName); bool Explicit = Override != ModuleFileOverrides.end(); @@ -1507,7 +1468,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, case ASTReader::ConfigurationMismatch: case ASTReader::HadErrors: ModuleLoader::HadFatalFailure = true; - // FIXME: The ASTReader will already have complained, but can we showhorn + // FIXME: The ASTReader will already have complained, but can we shoehorn // that diagnostic information into a more useful form? KnownModules[Path[0].first] = nullptr; return ModuleLoadResult(); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ff771fd00a3..29a935c9099 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2029,6 +2029,21 @@ void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) { Filename.assign(Buffer.begin(), Buffer.end()); } +static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) { + switch (ARR) { + case ASTReader::Failure: return true; + case ASTReader::Missing: return !(Caps & ASTReader::ARR_Missing); + case ASTReader::OutOfDate: return !(Caps & ASTReader::ARR_OutOfDate); + case ASTReader::VersionMismatch: return !(Caps & ASTReader::ARR_VersionMismatch); + case ASTReader::ConfigurationMismatch: + return !(Caps & ASTReader::ARR_ConfigurationMismatch); + case ASTReader::HadErrors: return true; + case ASTReader::Success: return false; + } + + llvm_unreachable("unknown ASTReadResult"); +} + ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, SmallVectorImpl<ImportedModule> &Loaded, @@ -2064,8 +2079,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, PP.getHeaderSearchInfo().getHeaderSearchOpts(); // All user input files reside at the index range [0, NumUserInputs), and - // system input files reside at [NumUserInputs, NumInputs). - if (!DisableValidation) { + // system input files reside at [NumUserInputs, NumInputs). For explicitly + // loaded module files, ignore missing inputs. + if (!DisableValidation && F.Kind != MK_ExplicitModule) { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; // If we are reading a module, we will create a verification timestamp, @@ -2181,10 +2197,23 @@ ASTReader::ReadControlBlock(ModuleFile &F, ASTFileSignature StoredSignature = Record[Idx++]; auto ImportedFile = ReadPath(F, Record, Idx); + // If our client can't cope with us being out of date, we can't cope with + // our dependency being missing. + unsigned Capabilities = ClientLoadCapabilities; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Capabilities &= ~ARR_Missing; + // Load the AST file. - switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded, - StoredSize, StoredModTime, StoredSignature, - ClientLoadCapabilities)) { + auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, + Loaded, StoredSize, StoredModTime, + StoredSignature, Capabilities); + + // If we diagnosed a problem, produce a backtrace. + if (isDiagnosedResult(Result, Capabilities)) + Diag(diag::note_module_file_imported_by) + << F.FileName << !F.ModuleName.empty() << F.ModuleName; + + switch (Result) { case Failure: return Failure; // If we have to ignore the dependency, we'll have to ignore this too. case Missing: @@ -3152,11 +3181,18 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr; if (!ModMap) { assert(ImportedBy && "top-level import should be verified"); - if ((ClientLoadCapabilities & ARR_Missing) == 0) - Diag(diag::err_imported_module_not_found) << F.ModuleName << F.FileName - << ImportedBy->FileName - << F.ModuleMapPath; - return Missing; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) { + if (auto *ASTFE = M ? M->getASTFile() : nullptr) + // This module was defined by an imported (explicit) module. + Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName + << ASTFE->getName(); + else + // This module was built with a different module map. + Diag(diag::err_imported_module_not_found) + << F.ModuleName << F.FileName << ImportedBy->FileName + << F.ModuleMapPath; + } + return OutOfDate; } assert(M->Name == F.ModuleName && "found module with different name"); @@ -3557,6 +3593,20 @@ static bool startsWithASTFileMagic(BitstreamCursor &Stream) { Stream.Read(8) == 'H'; } +static unsigned moduleKindForDiagnostic(ModuleKind Kind) { + switch (Kind) { + case MK_PCH: + return 0; // PCH + case MK_ImplicitModule: + case MK_ExplicitModule: + return 1; // module + case MK_MainFile: + case MK_Preamble: + return 2; // main source file + } + llvm_unreachable("unknown module kind"); +} + ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, @@ -3589,11 +3639,9 @@ ASTReader::ReadASTCore(StringRef FileName, return Missing; // Otherwise, return an error. - { - std::string Msg = "Unable to load module \"" + FileName.str() + "\": " - + ErrorStr; - Error(Msg); - } + Diag(diag::err_module_file_not_found) << moduleKindForDiagnostic(Type) + << FileName << ErrorStr.empty() + << ErrorStr; return Failure; case ModuleManager::OutOfDate: @@ -3603,11 +3651,9 @@ ASTReader::ReadASTCore(StringRef FileName, return OutOfDate; // Otherwise, return an error. - { - std::string Msg = "Unable to load module \"" + FileName.str() + "\": " - + ErrorStr; - Error(Msg); - } + Diag(diag::err_module_file_out_of_date) << moduleKindForDiagnostic(Type) + << FileName << ErrorStr.empty() + << ErrorStr; return Failure; } @@ -3628,7 +3674,8 @@ ASTReader::ReadASTCore(StringRef FileName, // Sniff for the signature. if (!startsWithASTFileMagic(Stream)) { - Diag(diag::err_not_a_pch_file) << FileName; + Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type) + << FileName; return Failure; } @@ -3661,6 +3708,18 @@ ASTReader::ReadASTCore(StringRef FileName, HaveReadControlBlock = true; switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) { case Success: + // Check that we didn't try to load a non-module AST file as a module. + // + // FIXME: Should we also perform the converse check? Loading a module as + // a PCH file sort of works, but it's a bit wonky. + if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule) && + F.ModuleName.empty()) { + auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure; + if (Result != OutOfDate || + (ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_module_file_not_module) << FileName; + return Result; + } break; case Failure: return Failure; @@ -3690,8 +3749,6 @@ ASTReader::ReadASTCore(StringRef FileName, break; } } - - return Success; } void ASTReader::InitializeContext() { |