diff options
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 82 |
1 files changed, 62 insertions, 20 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e4eddaef989..eac08545b16 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -37,6 +37,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Sanitizers.h" @@ -463,19 +464,9 @@ static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags, return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain); } -bool PCHValidator::ReadDiagnosticOptions( - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { - DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); - IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs()); - IntrusiveRefCntPtr<DiagnosticsEngine> Diags( - new DiagnosticsEngine(DiagIDs, DiagOpts.get())); - // This should never fail, because we would have processed these options - // before writing them to an ASTFile. - ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false); - - ModuleManager &ModuleMgr = Reader.getModuleManager(); - assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); - +/// Return the top import module if it is implicit, nullptr otherwise. +static Module *getTopImportImplicitModule(ModuleManager &ModuleMgr, + Preprocessor &PP) { // If the original import came from a file explicitly generated by the user, // don't check the diagnostic mappings. // FIXME: currently this is approximated by checking whether this is not a @@ -487,17 +478,37 @@ bool PCHValidator::ReadDiagnosticOptions( while (!TopImport->ImportedBy.empty()) TopImport = TopImport->ImportedBy[0]; if (TopImport->Kind != MK_ImplicitModule) - return false; + return nullptr; StringRef ModuleName = TopImport->ModuleName; assert(!ModuleName.empty() && "diagnostic options read before module name"); Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName); assert(M && "missing module"); + return M; +} + +bool PCHValidator::ReadDiagnosticOptions( + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { + DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); + IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs()); + IntrusiveRefCntPtr<DiagnosticsEngine> Diags( + new DiagnosticsEngine(DiagIDs, DiagOpts.get())); + // This should never fail, because we would have processed these options + // before writing them to an ASTFile. + ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false); + + ModuleManager &ModuleMgr = Reader.getModuleManager(); + assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); + + Module *TopM = getTopImportImplicitModule(ModuleMgr, PP); + if (!TopM) + return false; // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that // contains the union of their flags. - return checkDiagnosticMappings(*Diags, ExistingDiags, M->IsSystem, Complain); + return checkDiagnosticMappings(*Diags, ExistingDiags, TopM->IsSystem, + Complain); } /// \brief Collect the macro definitions provided by the given preprocessor @@ -4064,12 +4075,41 @@ ASTReader::readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy, Listener.get(), WasImportedBy ? false : HSOpts.ModulesValidateDiagnosticOptions); + // If F was directly imported by another module, it's implicitly validated by + // the importing module. if (DisableValidation || WasImportedBy || (AllowConfigurationMismatch && Result == ConfigurationMismatch)) return Success; - if (Result == Failure) + if (Result == Failure) { Error("malformed block record in AST file"); + return Failure; + } + + if (Result == OutOfDate && F.Kind == MK_ImplicitModule) { + // If this module has already been finalized in the PCMCache, we're stuck + // with it; we can only load a single version of each module. + // + // This can happen when a module is imported in two contexts: in one, as a + // user module; in another, as a system module (due to an import from + // another module marked with the [system] flag). It usually indicates a + // bug in the module map: this module should also be marked with [system]. + // + // If -Wno-system-headers (the default), and the first import is as a + // system module, then validation will fail during the as-user import, + // since -Werror flags won't have been validated. However, it's reasonable + // to treat this consistently as a system module. + // + // If -Wsystem-headers, the PCM on disk was built with + // -Wno-system-headers, and the first import is as a user module, then + // validation will fail during the as-system import since the PCM on disk + // doesn't guarantee that -Werror was respected. However, the -Werror + // flags were checked during the initial as-user import. + if (PCMCache.isBufferFinal(F.FileName)) { + Diag(diag::warn_module_system_bit_conflict) << F.FileName; + return Success; + } + } return Result; } @@ -4122,7 +4162,7 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl( if (Listener && ValidateDiagnosticOptions && !AllowCompatibleConfigurationMismatch && ParseDiagnosticOptions(Record, Complain, *Listener)) - return OutOfDate; + Result = OutOfDate; // Don't return early. Read the signature. break; } case DIAG_PRAGMA_MAPPINGS: @@ -7301,7 +7341,7 @@ LLVM_DUMP_METHOD void ASTReader::dump() { /// by heap-backed versus mmap'ed memory. void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { for (ModuleFile &I : ModuleMgr) { - if (llvm::MemoryBuffer *buf = I.Buffer.get()) { + if (llvm::MemoryBuffer *buf = I.Buffer) { size_t bytes = buf->getBufferSize(); switch (buf->getBufferKind()) { case llvm::MemoryBuffer::MemoryBuffer_Malloc: @@ -9628,8 +9668,10 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, : cast<ASTReaderListener>(new PCHValidator(PP, *this))), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP), - Context(Context), ModuleMgr(PP.getFileManager(), PCHContainerRdr), - DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot), + Context(Context), + ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr), + PCMCache(PP.getPCMCache()), DummyIdResolver(PP), + ReadTimer(std::move(ReadTimer)), isysroot(isysroot), DisableValidation(DisableValidation), AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), AllowConfigurationMismatch(AllowConfigurationMismatch), |