diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp | 2025 |
1 files changed, 1381 insertions, 644 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index 4d1b4b9..ae41654 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -22,6 +22,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" @@ -29,6 +30,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Basic/VersionTuple.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" @@ -49,16 +51,100 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" -#include "llvm/Support/system_error.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstdio> #include <iterator> +#include <system_error> using namespace clang; using namespace clang::serialization; using namespace clang::serialization::reader; using llvm::BitstreamCursor; + +//===----------------------------------------------------------------------===// +// ChainedASTReaderListener implementation +//===----------------------------------------------------------------------===// + +bool +ChainedASTReaderListener::ReadFullVersionInformation(StringRef FullVersion) { + return First->ReadFullVersionInformation(FullVersion) || + Second->ReadFullVersionInformation(FullVersion); +} +void ChainedASTReaderListener::ReadModuleName(StringRef ModuleName) { + First->ReadModuleName(ModuleName); + Second->ReadModuleName(ModuleName); +} +void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) { + First->ReadModuleMapFile(ModuleMapPath); + Second->ReadModuleMapFile(ModuleMapPath); +} +bool ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) { + return First->ReadLanguageOptions(LangOpts, Complain) || + Second->ReadLanguageOptions(LangOpts, Complain); +} +bool +ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) { + return First->ReadTargetOptions(TargetOpts, Complain) || + Second->ReadTargetOptions(TargetOpts, Complain); +} +bool ChainedASTReaderListener::ReadDiagnosticOptions( + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { + return First->ReadDiagnosticOptions(DiagOpts, Complain) || + Second->ReadDiagnosticOptions(DiagOpts, Complain); +} +bool +ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts, + bool Complain) { + return First->ReadFileSystemOptions(FSOpts, Complain) || + Second->ReadFileSystemOptions(FSOpts, Complain); +} + +bool ChainedASTReaderListener::ReadHeaderSearchOptions( + const HeaderSearchOptions &HSOpts, bool Complain) { + return First->ReadHeaderSearchOptions(HSOpts, Complain) || + Second->ReadHeaderSearchOptions(HSOpts, Complain); +} +bool ChainedASTReaderListener::ReadPreprocessorOptions( + const PreprocessorOptions &PPOpts, bool Complain, + std::string &SuggestedPredefines) { + return First->ReadPreprocessorOptions(PPOpts, Complain, + SuggestedPredefines) || + Second->ReadPreprocessorOptions(PPOpts, Complain, SuggestedPredefines); +} +void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M, + unsigned Value) { + First->ReadCounter(M, Value); + Second->ReadCounter(M, Value); +} +bool ChainedASTReaderListener::needsInputFileVisitation() { + return First->needsInputFileVisitation() || + Second->needsInputFileVisitation(); +} +bool ChainedASTReaderListener::needsSystemInputFileVisitation() { + return First->needsSystemInputFileVisitation() || + Second->needsSystemInputFileVisitation(); +} +void ChainedASTReaderListener::visitModuleFile(StringRef Filename) { + First->visitModuleFile(Filename); + Second->visitModuleFile(Filename); +} +bool ChainedASTReaderListener::visitInputFile(StringRef Filename, + bool isSystem, + bool isOverridden) { + bool Continue = false; + if (First->needsInputFileVisitation() && + (!isSystem || First->needsSystemInputFileVisitation())) + Continue |= First->visitInputFile(Filename, isSystem, isOverridden); + if (Second->needsInputFileVisitation() && + (!isSystem || Second->needsSystemInputFileVisitation())) + Continue |= Second->visitInputFile(Filename, isSystem, isOverridden); + return Continue; +} + //===----------------------------------------------------------------------===// // PCH validator implementation //===----------------------------------------------------------------------===// @@ -140,8 +226,6 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts, CHECK_TARGET_OPT(Triple, "target"); CHECK_TARGET_OPT(CPU, "target CPU"); CHECK_TARGET_OPT(ABI, "target ABI"); - CHECK_TARGET_OPT(CXXABI, "target C++ ABI"); - CHECK_TARGET_OPT(LinkerVersion, "target linker version"); #undef CHECK_TARGET_OPT // Compare feature sets. @@ -197,14 +281,14 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts, bool Complain) { const LangOptions &ExistingLangOpts = PP.getLangOpts(); return checkLanguageOptions(LangOpts, ExistingLangOpts, - Complain? &Reader.Diags : 0); + Complain? &Reader.Diags : nullptr); } bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain) { const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts(); return checkTargetOptions(TargetOpts, ExistingTargetOpts, - Complain? &Reader.Diags : 0); + Complain? &Reader.Diags : nullptr); } namespace { @@ -214,11 +298,124 @@ namespace { DeclsMap; } +static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags, + DiagnosticsEngine &Diags, + bool Complain) { + typedef DiagnosticsEngine::Level Level; + + // Check current mappings for new -Werror mappings, and the stored mappings + // for cases that were explicitly mapped to *not* be errors that are now + // errors because of options like -Werror. + DiagnosticsEngine *MappingSources[] = { &Diags, &StoredDiags }; + + for (DiagnosticsEngine *MappingSource : MappingSources) { + for (auto DiagIDMappingPair : MappingSource->getDiagnosticMappings()) { + diag::kind DiagID = DiagIDMappingPair.first; + Level CurLevel = Diags.getDiagnosticLevel(DiagID, SourceLocation()); + if (CurLevel < DiagnosticsEngine::Error) + continue; // not significant + Level StoredLevel = + StoredDiags.getDiagnosticLevel(DiagID, SourceLocation()); + if (StoredLevel < DiagnosticsEngine::Error) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror=" + + Diags.getDiagnosticIDs()->getWarningOptionForDiag(DiagID).str(); + return true; + } + } + } + + return false; +} + +static bool isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) { + diag::Severity Ext = Diags.getExtensionHandlingBehavior(); + if (Ext == diag::Severity::Warning && Diags.getWarningsAsErrors()) + return true; + return Ext >= diag::Severity::Error; +} + +static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags, + DiagnosticsEngine &Diags, + bool IsSystem, bool Complain) { + // Top-level options + if (IsSystem) { + if (Diags.getSuppressSystemWarnings()) + return false; + // If -Wsystem-headers was not enabled before, be conservative + if (StoredDiags.getSuppressSystemWarnings()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Wsystem-headers"; + return true; + } + } + + if (Diags.getWarningsAsErrors() && !StoredDiags.getWarningsAsErrors()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror"; + return true; + } + + if (Diags.getWarningsAsErrors() && Diags.getEnableAllWarnings() && + !StoredDiags.getEnableAllWarnings()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Weverything -Werror"; + return true; + } + + if (isExtHandlingFromDiagsError(Diags) && + !isExtHandlingFromDiagsError(StoredDiags)) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-pedantic-errors"; + return true; + } + + 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"); + + // 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 + // module import. + // Note: ModuleMgr.rbegin() may not be the current module, but it must be in + // the transitive closure of its imports, since unrelated modules cannot be + // imported until after this module finishes validation. + ModuleFile *TopImport = *ModuleMgr.rbegin(); + while (!TopImport->ImportedBy.empty()) + TopImport = TopImport->ImportedBy[0]; + if (TopImport->Kind != MK_Module) + return false; + + StringRef ModuleName = TopImport->ModuleName; + assert(!ModuleName.empty() && "diagnostic options read before module name"); + + Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName); + assert(M && "missing module"); + + // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that + // contains the union of their flags. + return checkDiagnosticMappings(*Diags, ExistingDiags, M->IsSystem, Complain); +} + /// \brief Collect the macro definitions provided by the given preprocessor /// options. -static void collectMacroDefinitions(const PreprocessorOptions &PPOpts, - MacroDefinitionsMap &Macros, - SmallVectorImpl<StringRef> *MacroNames = 0){ +static void +collectMacroDefinitions(const PreprocessorOptions &PPOpts, + MacroDefinitionsMap &Macros, + SmallVectorImpl<StringRef> *MacroNames = nullptr) { for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) { StringRef Macro = PPOpts.Macros[I].first; bool IsUndef = PPOpts.Macros[I].second; @@ -373,7 +570,7 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts(); return checkPreprocessorOptions(PPOpts, ExistingPPOpts, - Complain? &Reader.Diags : 0, + Complain? &Reader.Diags : nullptr, PP.getFileManager(), SuggestedPredefines, PP.getLangOpts()); @@ -387,9 +584,10 @@ void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { // AST reader implementation //===----------------------------------------------------------------------===// -void -ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) { +void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener, + bool TakeOwnership) { DeserializationListener = Listener; + OwnsDeserializationListener = TakeOwnership; } @@ -401,19 +599,19 @@ unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { std::pair<unsigned, unsigned> ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } ASTSelectorLookupTrait::internal_key_type ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; + using namespace llvm::support; SelectorTable &SelTable = Reader.getContext().Selectors; - unsigned N = ReadUnalignedLE16(d); - IdentifierInfo *FirstII - = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); + unsigned N = endian::readNext<uint16_t, little, unaligned>(d); + IdentifierInfo *FirstII = Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d)); if (N == 0) return SelTable.getNullarySelector(FirstII); else if (N == 1) @@ -422,7 +620,8 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { SmallVector<IdentifierInfo *, 16> Args; Args.push_back(FirstII); for (unsigned I = 1; I != N; ++I) - Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d))); + Args.push_back(Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d))); return SelTable.getSelector(N, Args.data()); } @@ -430,13 +629,16 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { ASTSelectorLookupTrait::data_type ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; + using namespace llvm::support; data_type Result; - Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d)); - unsigned NumInstanceMethodsAndBits = ReadUnalignedLE16(d); - unsigned NumFactoryMethodsAndBits = ReadUnalignedLE16(d); + Result.ID = Reader.getGlobalSelectorID( + F, endian::readNext<uint32_t, little, unaligned>(d)); + unsigned NumInstanceMethodsAndBits = + endian::readNext<uint16_t, little, unaligned>(d); + unsigned NumFactoryMethodsAndBits = + endian::readNext<uint16_t, little, unaligned>(d); Result.InstanceBits = NumInstanceMethodsAndBits & 0x3; Result.FactoryBits = NumFactoryMethodsAndBits & 0x3; unsigned NumInstanceMethods = NumInstanceMethodsAndBits >> 2; @@ -444,15 +646,15 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, // Load instance methods for (unsigned I = 0; I != NumInstanceMethods; ++I) { - if (ObjCMethodDecl *Method - = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) + if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( + F, endian::readNext<uint32_t, little, unaligned>(d))) Result.Instance.push_back(Method); } // Load factory methods for (unsigned I = 0; I != NumFactoryMethods; ++I) { - if (ObjCMethodDecl *Method - = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) + if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( + F, endian::readNext<uint32_t, little, unaligned>(d))) Result.Factory.push_back(Method); } @@ -465,9 +667,9 @@ unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) { std::pair<unsigned, unsigned> ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned DataLen = ReadUnalignedLE16(d); - unsigned KeyLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } @@ -490,8 +692,8 @@ static bool isInterestingIdentifier(IdentifierInfo &II) { IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - unsigned RawID = ReadUnalignedLE32(d); + using namespace llvm::support; + unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); bool IsInteresting = RawID & 0x01; // Wipe out the "is interesting" bit. @@ -517,8 +719,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, return II; } - unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d); - unsigned Bits = ReadUnalignedLE16(d); + unsigned ObjCOrBuiltinID = endian::readNext<uint16_t, little, unaligned>(d); + unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d); bool CPlusPlusOperatorKeyword = Bits & 0x01; Bits >>= 1; bool HasRevertedTokenIDToIdentifier = Bits & 0x01; @@ -567,11 +769,13 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // If this identifier is a macro, deserialize the macro // definition. if (hadMacroDefinition) { - uint32_t MacroDirectivesOffset = ReadUnalignedLE32(d); + uint32_t MacroDirectivesOffset = + endian::readNext<uint32_t, little, unaligned>(d); DataLen -= 4; SmallVector<uint32_t, 8> LocalMacroIDs; if (hasSubmoduleMacros) { - while (uint32_t LocalMacroID = ReadUnalignedLE32(d)) { + while (uint32_t LocalMacroID = + endian::readNext<uint32_t, little, unaligned>(d)) { DataLen -= 4; LocalMacroIDs.push_back(LocalMacroID); } @@ -579,11 +783,34 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, } if (F.Kind == MK_Module) { + // Macro definitions are stored from newest to oldest, so reverse them + // before registering them. + llvm::SmallVector<unsigned, 8> MacroSizes; for (SmallVectorImpl<uint32_t>::iterator - I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; ++I) { - MacroID MacID = Reader.getGlobalMacroID(F, *I); - Reader.addPendingMacroFromModule(II, &F, MacID, F.DirectImportLoc); + I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) { + unsigned Size = 1; + + static const uint32_t HasOverridesFlag = 0x80000000U; + if (I + 1 != E && (I[1] & HasOverridesFlag)) + Size += 1 + (I[1] & ~HasOverridesFlag); + + MacroSizes.push_back(Size); + I += Size; + } + + SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end(); + for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(), + SE = MacroSizes.rend(); + SI != SE; ++SI) { + I -= *SI; + + uint32_t LocalMacroID = *I; + ArrayRef<uint32_t> Overrides; + if (*SI != 1) + Overrides = llvm::makeArrayRef(&I[2], *SI - 2); + Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides); } + assert(I == LocalMacroIDs.begin()); } else { Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset); } @@ -596,7 +823,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, if (DataLen > 0) { SmallVector<uint32_t, 4> DeclIDs; for (; DataLen > 0; DataLen -= 4) - DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d))); + DeclIDs.push_back(Reader.getGlobalDeclID( + F, endian::readNext<uint32_t, little, unaligned>(d))); Reader.SetGloballyVisibleDecls(II, DeclIDs); } @@ -664,34 +892,37 @@ ASTDeclContextNameLookupTrait::GetInternalKey( std::pair<unsigned, unsigned> ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } ASTDeclContextNameLookupTrait::internal_key_type ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; + using namespace llvm::support; DeclNameKey Key; Key.Kind = (DeclarationName::NameKind)*d++; switch (Key.Kind) { case DeclarationName::Identifier: - Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); + Key.Data = (uint64_t)Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d)); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: Key.Data = - (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d)) - .getAsOpaquePtr(); + (uint64_t)Reader.getLocalSelector( + F, endian::readNext<uint32_t, little, unaligned>( + d)).getAsOpaquePtr(); break; case DeclarationName::CXXOperatorName: Key.Data = *d++; // OverloadedOperatorKind break; case DeclarationName::CXXLiteralOperatorName: - Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); + Key.Data = (uint64_t)Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d)); break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: @@ -708,8 +939,8 @@ ASTDeclContextNameLookupTrait::data_type ASTDeclContextNameLookupTrait::ReadData(internal_key_type, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - unsigned NumDecls = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned NumDecls = endian::readNext<uint16_t, little, unaligned>(d); LE32DeclID *Start = reinterpret_cast<LE32DeclID *>( const_cast<unsigned char *>(d)); return std::make_pair(Start, Start + NumDecls); @@ -749,11 +980,11 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M, Error("Expected visible lookup table block"); return true; } - Info.NameLookupTableData - = ASTDeclContextNameLookupTable::Create( - (const unsigned char *)Blob.data() + Record[0], - (const unsigned char *)Blob.data(), - ASTDeclContextNameLookupTrait(*this, M)); + Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create( + (const unsigned char *)Blob.data() + Record[0], + (const unsigned char *)Blob.data() + sizeof(uint32_t), + (const unsigned char *)Blob.data(), + ASTDeclContextNameLookupTrait(*this, M)); } return false; @@ -1023,8 +1254,8 @@ bool ASTReader::ReadSLocEntry(int ID) { llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name); - SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID, - BaseOffset + Offset, IncludeLoc); + SourceMgr.createFileID(Buffer, FileCharacter, ID, BaseOffset + Offset, + IncludeLoc); break; } @@ -1059,7 +1290,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { // FIXME: Can we map this down to a particular submodule? That would be // ideal. - return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName)); + return std::make_pair(M->ImportLoc, StringRef(M->ModuleName)); } /// \brief Find the location where the module F is imported. @@ -1070,14 +1301,10 @@ SourceLocation ASTReader::getImportLocation(ModuleFile *F) { // Otherwise we have a PCH. It's considered to be "imported" at the first // location of its includer. if (F->ImportedBy.empty() || !F->ImportedBy[0]) { - // Main file is the importer. We assume that it is the first entry in the - // entry table. We can't ask the manager, because at the time of PCH loading - // the main file entry doesn't exist yet. - // The very first entry is the invalid instantiation loc, which takes up - // offsets 0 and 1. - return SourceLocation::getFromRawEncoding(2U); - } - //return F->Loaders[0]->FirstLoc; + // Main file is the importer. + assert(!SourceMgr.getMainFileID().isInvalid() && "missing main file"); + return SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); + } return F->ImportedBy[0]->FirstLoc; } @@ -1126,7 +1353,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { Stream.JumpToBit(Offset); RecordData Record; SmallVector<IdentifierInfo*, 16> MacroArgs; - MacroInfo *Macro = 0; + MacroInfo *Macro = nullptr; while (true) { // Advance to the next record, but if we get to the end of the block, don't @@ -1169,6 +1396,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, SubModID); MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex)); MI->setIsUsed(Record[NextIndex++]); + MI->setUsedForHeaderGuard(Record[NextIndex++]); if (RecType == PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. @@ -1214,7 +1442,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { case PP_TOKEN: { // If we see a TOKEN before a PP_MACRO_*, then the file is // erroneous, just pretend we didn't see this. - if (Macro == 0) break; + if (!Macro) break; unsigned Idx = 0; Token Tok = ReadToken(F, Record, Idx); @@ -1262,16 +1490,18 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) { std::pair<unsigned, unsigned> HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) { - unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = (unsigned) endian::readNext<uint16_t, little, unaligned>(d); unsigned DataLen = (unsigned) *d++; return std::make_pair(KeyLen, DataLen); } HeaderFileInfoTrait::internal_key_type HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { + using namespace llvm::support; internal_key_type ikey; - ikey.Size = off_t(clang::io::ReadUnalignedLE64(d)); - ikey.ModTime = time_t(clang::io::ReadUnalignedLE64(d)); + ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d)); + ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d)); ikey.Filename = (const char *)d; return ikey; } @@ -1280,7 +1510,7 @@ HeaderFileInfoTrait::data_type HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, unsigned DataLen) { const unsigned char *End = d + DataLen; - using namespace clang::io; + using namespace llvm::support; HeaderFileInfo HFI; unsigned Flags = *d++; HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole> @@ -1290,10 +1520,11 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, HFI.DirInfo = (Flags >> 2) & 0x03; HFI.Resolved = (Flags >> 1) & 0x01; HFI.IndexHeaderMapHeader = Flags & 0x01; - HFI.NumIncludes = ReadUnalignedLE16(d); - HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M, - ReadUnalignedLE32(d)); - if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) { + HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d); + HFI.ControllingMacroID = Reader.getGlobalIdentifierID( + M, endian::readNext<uint32_t, little, unaligned>(d)); + if (unsigned FrameworkOffset = + endian::readNext<uint32_t, little, unaligned>(d)) { // The framework offset is 1 greater than the actual offset, // since 0 is used as an indicator for "no framework name". StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1); @@ -1301,7 +1532,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, } if (d != End) { - uint32_t LocalSMID = ReadUnalignedLE32(d); + uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d); if (LocalSMID) { // This header is part of a module. Associate it with the module to enable // implicit module import. @@ -1323,12 +1554,19 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, return HFI; } -void ASTReader::addPendingMacroFromModule(IdentifierInfo *II, - ModuleFile *M, - GlobalMacroID GMacID, - SourceLocation ImportLoc) { +void +ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M, + GlobalMacroID GMacID, + ArrayRef<SubmoduleID> Overrides) { assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); - PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, ImportLoc)); + SubmoduleID *OverrideData = nullptr; + if (!Overrides.empty()) { + OverrideData = new (Context) SubmoduleID[Overrides.size() + 1]; + OverrideData[0] = Overrides.size(); + for (unsigned I = 0; I != Overrides.size(); ++I) + OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]); + } + PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData)); } void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II, @@ -1452,7 +1690,7 @@ void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { // If there is a global index, look there first to determine which modules // provably do not have any results for this identifier. GlobalModuleIndex::HitSet Hits; - GlobalModuleIndex::HitSet *HitsPtr = 0; + GlobalModuleIndex::HitSet *HitsPtr = nullptr; if (!loadGlobalIndex()) { if (GlobalIndex->lookupIdentifier(II.getName(), Hits)) { HitsPtr = &Hits; @@ -1474,7 +1712,60 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { // Update the generation for this identifier. if (getContext().getLangOpts().Modules) - IdentifierGeneration[II] = CurrentGeneration; + IdentifierGeneration[II] = getGeneration(); +} + +struct ASTReader::ModuleMacroInfo { + SubmoduleID SubModID; + MacroInfo *MI; + SubmoduleID *Overrides; + // FIXME: Remove this. + ModuleFile *F; + + bool isDefine() const { return MI; } + + SubmoduleID getSubmoduleID() const { return SubModID; } + + ArrayRef<SubmoduleID> getOverriddenSubmodules() const { + if (!Overrides) + return None; + return llvm::makeArrayRef(Overrides + 1, *Overrides); + } + + DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const { + if (!MI) + return nullptr; + return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true); + } +}; + +ASTReader::ModuleMacroInfo * +ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) { + ModuleMacroInfo Info; + + uint32_t ID = PMInfo.ModuleMacroData.MacID; + if (ID & 1) { + // Macro undefinition. + Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1); + Info.MI = nullptr; + } else { + // Macro definition. + GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1); + assert(GMacID); + + // If this macro has already been loaded, don't do so again. + // FIXME: This is highly dubious. Multiple macro definitions can have the + // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc. + if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS]) + return nullptr; + + Info.MI = getMacro(GMacID); + Info.SubModID = Info.MI->getOwningModuleID(); + } + Info.Overrides = PMInfo.ModuleMacroData.Overrides; + Info.F = PMInfo.M; + + return new (Context) ModuleMacroInfo(Info); } void ASTReader::resolvePendingMacro(IdentifierInfo *II, @@ -1486,42 +1777,21 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, PMInfo.PCHMacroData.MacroDirectivesOffset); return; } - - // Module Macro. - GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID; - SourceLocation ImportLoc = - SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc); + // Module Macro. - assert(GMacID); - // If this macro has already been loaded, don't do so again. - if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS]) + ModuleMacroInfo *MMI = getModuleMacro(PMInfo); + if (!MMI) return; - MacroInfo *MI = getMacro(GMacID); - SubmoduleID SubModID = MI->getOwningModuleID(); - MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc, - /*isImported=*/true); - - // Determine whether this macro definition is visible. - bool Hidden = false; - Module *Owner = 0; - if (SubModID) { - if ((Owner = getSubmodule(SubModID))) { - if (Owner->NameVisibility == Module::Hidden) { - // The owning module is not visible, and this macro definition - // should not be, either. - Hidden = true; - - // Note that this macro definition was hidden because its owning - // module is not yet visible. - HiddenNamesMap[Owner].push_back(HiddenName(II, MD)); - } - } + Module *Owner = getSubmodule(MMI->getSubmoduleID()); + if (Owner && Owner->NameVisibility == Module::Hidden) { + // Macros in the owning module are hidden. Just remember this macro to + // install if we make this module visible. + HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI)); + } else { + installImportedMacro(II, MMI, Owner, /*FromFinalization*/false); } - - if (!Hidden) - installImportedMacro(II, MD, Owner); } void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, @@ -1548,10 +1818,10 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, } // Deserialize the macro directives history in reverse source-order. - MacroDirective *Latest = 0, *Earliest = 0; + MacroDirective *Latest = nullptr, *Earliest = nullptr; unsigned Idx = 0, N = Record.size(); while (Idx < N) { - MacroDirective *MD = 0; + MacroDirective *MD = nullptr; SourceLocation Loc = ReadSourceLocation(M, Record, Idx); MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++]; switch (K) { @@ -1591,7 +1861,7 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, Module *NewOwner, ASTReader &Reader) { assert(PrevMI && NewMI); - Module *PrevOwner = 0; + Module *PrevOwner = nullptr; if (SubmoduleID PrevModID = PrevMI->getOwningModuleID()) PrevOwner = Reader.getSubmodule(PrevModID); SourceManager &SrcMgr = Reader.getSourceManager(); @@ -1606,34 +1876,181 @@ static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, return PrevInSystem && NewInSystem; } -void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD, - Module *Owner) { - assert(II && MD); +void ASTReader::removeOverriddenMacros(IdentifierInfo *II, + AmbiguousMacros &Ambig, + ArrayRef<SubmoduleID> Overrides) { + for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) { + SubmoduleID OwnerID = Overrides[OI]; + + // If this macro is not yet visible, remove it from the hidden names list. + Module *Owner = getSubmodule(OwnerID); + HiddenNames &Hidden = HiddenNamesMap[Owner]; + HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II); + if (HI != Hidden.HiddenMacros.end()) { + auto SubOverrides = HI->second->getOverriddenSubmodules(); + Hidden.HiddenMacros.erase(HI); + removeOverriddenMacros(II, Ambig, SubOverrides); + } + + // If this macro is already in our list of conflicts, remove it from there. + Ambig.erase( + std::remove_if(Ambig.begin(), Ambig.end(), [&](DefMacroDirective *MD) { + return MD->getInfo()->getOwningModuleID() == OwnerID; + }), + Ambig.end()); + } +} - DefMacroDirective *DefMD = cast<DefMacroDirective>(MD); +ASTReader::AmbiguousMacros * +ASTReader::removeOverriddenMacros(IdentifierInfo *II, + ArrayRef<SubmoduleID> Overrides) { MacroDirective *Prev = PP.getMacroDirective(II); - if (Prev) { - MacroDirective::DefInfo PrevDef = Prev->getDefinition(); - MacroInfo *PrevMI = PrevDef.getMacroInfo(); - MacroInfo *NewMI = DefMD->getInfo(); - if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP, - /*Syntactically=*/true)) { - // Before marking the macros as ambiguous, check if this is a case where - // both macros are in system headers. If so, we trust that the system - // did not get it wrong. This also handles cases where Clang's own - // headers have a different spelling of certain system macros: - // #define LONG_MAX __LONG_MAX__ (clang's limits.h) - // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) - if (!areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) { - PrevDef.getDirective()->setAmbiguous(true); - DefMD->setAmbiguous(true); - } + if (!Prev && Overrides.empty()) + return nullptr; + + DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective() + : nullptr; + if (PrevDef && PrevDef->isAmbiguous()) { + // We had a prior ambiguity. Check whether we resolve it (or make it worse). + AmbiguousMacros &Ambig = AmbiguousMacroDefs[II]; + Ambig.push_back(PrevDef); + + removeOverriddenMacros(II, Ambig, Overrides); + + if (!Ambig.empty()) + return &Ambig; + + AmbiguousMacroDefs.erase(II); + } else { + // There's no ambiguity yet. Maybe we're introducing one. + AmbiguousMacros Ambig; + if (PrevDef) + Ambig.push_back(PrevDef); + + removeOverriddenMacros(II, Ambig, Overrides); + + if (!Ambig.empty()) { + AmbiguousMacros &Result = AmbiguousMacroDefs[II]; + std::swap(Result, Ambig); + return &Result; } } - + + // We ended up with no ambiguity. + return nullptr; +} + +void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, + Module *Owner, bool FromFinalization) { + assert(II && Owner); + + SourceLocation ImportLoc = Owner->MacroVisibilityLoc; + if (ImportLoc.isInvalid() && !FromFinalization) { + // FIXME: If we made macros from this module visible but didn't provide a + // source location for the import, we don't have a location for the macro. + // Use the location at which the containing module file was first imported + // for now. + ImportLoc = MMI->F->DirectImportLoc; + assert(ImportLoc.isValid() && "no import location for a visible macro?"); + } + + AmbiguousMacros *Prev = + removeOverriddenMacros(II, MMI->getOverriddenSubmodules()); + + // Create a synthetic macro definition corresponding to the import (or null + // if this was an undefinition of the macro). + DefMacroDirective *MD = MMI->import(PP, ImportLoc); + + // If there's no ambiguity, just install the macro. + if (!Prev) { + if (MD) + PP.appendMacroDirective(II, MD); + else + PP.appendMacroDirective(II, PP.AllocateUndefMacroDirective(ImportLoc)); + return; + } + assert(!Prev->empty()); + + if (!MD) { + // We imported a #undef that didn't remove all prior definitions. The most + // recent prior definition remains, and we install it in the place of the + // imported directive. + MacroInfo *NewMI = Prev->back()->getInfo(); + Prev->pop_back(); + MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc, /*Imported*/true); + } + + // We're introducing a macro definition that creates or adds to an ambiguity. + // We can resolve that ambiguity if this macro is token-for-token identical to + // all of the existing definitions. + MacroInfo *NewMI = MD->getInfo(); + assert(NewMI && "macro definition with no MacroInfo?"); + while (!Prev->empty()) { + MacroInfo *PrevMI = Prev->back()->getInfo(); + assert(PrevMI && "macro definition with no MacroInfo?"); + + // Before marking the macros as ambiguous, check if this is a case where + // both macros are in system headers. If so, we trust that the system + // did not get it wrong. This also handles cases where Clang's own + // headers have a different spelling of certain system macros: + // #define LONG_MAX __LONG_MAX__ (clang's limits.h) + // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) + // + // FIXME: Remove the defined-in-system-headers check. clang's limits.h + // overrides the system limits.h's macros, so there's no conflict here. + if (NewMI != PrevMI && + !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) && + !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) + break; + + // The previous definition is the same as this one (or both are defined in + // system modules so we can assume they're equivalent); we don't need to + // track it any more. + Prev->pop_back(); + } + + if (!Prev->empty()) + MD->setAmbiguous(true); + PP.appendMacroDirective(II, MD); } +ASTReader::InputFileInfo +ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { + // Go find this input file. + BitstreamCursor &Cursor = F.InputFilesCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(F.InputFileOffsets[ID-1]); + + unsigned Code = Cursor.ReadCode(); + RecordData Record; + StringRef Blob; + + unsigned Result = Cursor.readRecord(Code, Record, &Blob); + assert(static_cast<InputFileRecordTypes>(Result) == INPUT_FILE && + "invalid record type for input file"); + (void)Result; + + std::string Filename; + off_t StoredSize; + time_t StoredTime; + bool Overridden; + + assert(Record[0] == ID && "Bogus stored ID or offset"); + StoredSize = static_cast<off_t>(Record[1]); + StoredTime = static_cast<time_t>(Record[2]); + Overridden = static_cast<bool>(Record[3]); + Filename = Blob; + MaybeAddSystemRootToFilename(F, Filename); + + InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden }; + return R; +} + +std::string ASTReader::getInputFileName(ModuleFile &F, unsigned int ID) { + return readInputFileInfo(F, ID).Filename; +} + InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { // If this ID is bogus, just return an empty input file. if (ID == 0 || ID > F.InputFilesLoaded.size()) @@ -1643,107 +2060,113 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { if (F.InputFilesLoaded[ID-1].getFile()) return F.InputFilesLoaded[ID-1]; + if (F.InputFilesLoaded[ID-1].isNotFound()) + return InputFile(); + // Go find this input file. BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(F.InputFileOffsets[ID-1]); - unsigned Code = Cursor.ReadCode(); - RecordData Record; - StringRef Blob; - switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { - case INPUT_FILE: { - unsigned StoredID = Record[0]; - assert(ID == StoredID && "Bogus stored ID or offset"); - (void)StoredID; - off_t StoredSize = (off_t)Record[1]; - time_t StoredTime = (time_t)Record[2]; - bool Overridden = (bool)Record[3]; - - // Get the file entry for this input file. - StringRef OrigFilename = Blob; - std::string Filename = OrigFilename; - MaybeAddSystemRootToFilename(F, Filename); - const FileEntry *File - = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime) - : FileMgr.getFile(Filename, /*OpenFile=*/false); - - // If we didn't find the file, resolve it relative to the - // original directory from which this AST file was created. - if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() && - F.OriginalDir != CurrentDir) { - std::string Resolved = resolveFileRelativeToOriginalDir(Filename, - F.OriginalDir, - CurrentDir); - if (!Resolved.empty()) - File = FileMgr.getFile(Resolved); - } - - // For an overridden file, create a virtual file with the stored - // size/timestamp. - if (Overridden && File == 0) { - File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); - } - - if (File == 0) { - if (Complain) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by AST file"; - Error(ErrorStr.c_str()); - } - return InputFile(); - } + InputFileInfo FI = readInputFileInfo(F, ID); + off_t StoredSize = FI.StoredSize; + time_t StoredTime = FI.StoredTime; + bool Overridden = FI.Overridden; + StringRef Filename = FI.Filename; + + const FileEntry *File + = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime) + : FileMgr.getFile(Filename, /*OpenFile=*/false); + + // If we didn't find the file, resolve it relative to the + // original directory from which this AST file was created. + if (File == nullptr && !F.OriginalDir.empty() && !CurrentDir.empty() && + F.OriginalDir != CurrentDir) { + std::string Resolved = resolveFileRelativeToOriginalDir(Filename, + F.OriginalDir, + CurrentDir); + if (!Resolved.empty()) + File = FileMgr.getFile(Resolved); + } - // Check if there was a request to override the contents of the file - // that was part of the precompiled header. Overridding such a file - // can lead to problems when lexing using the source locations from the - // PCH. - SourceManager &SM = getSourceManager(); - if (!Overridden && SM.isFileOverridden(File)) { - if (Complain) - Error(diag::err_fe_pch_file_overridden, Filename); - // After emitting the diagnostic, recover by disabling the override so - // that the original file will be used. - SM.disableFileContentsOverride(File); - // The FileEntry is a virtual file entry with the size of the contents - // that would override the original contents. Set it to the original's - // size/time. - FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), - StoredSize, StoredTime); - } + // For an overridden file, create a virtual file with the stored + // size/timestamp. + if (Overridden && File == nullptr) { + File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); + } - bool IsOutOfDate = false; + if (File == nullptr) { + if (Complain) { + std::string ErrorStr = "could not find file '"; + ErrorStr += Filename; + ErrorStr += "' referenced by AST file"; + Error(ErrorStr.c_str()); + } + // Record that we didn't find the file. + F.InputFilesLoaded[ID-1] = InputFile::getNotFound(); + return InputFile(); + } - // For an overridden file, there is nothing to validate. - if (!Overridden && (StoredSize != File->getSize() + // Check if there was a request to override the contents of the file + // that was part of the precompiled header. Overridding such a file + // can lead to problems when lexing using the source locations from the + // PCH. + SourceManager &SM = getSourceManager(); + if (!Overridden && SM.isFileOverridden(File)) { + if (Complain) + Error(diag::err_fe_pch_file_overridden, Filename); + // After emitting the diagnostic, recover by disabling the override so + // that the original file will be used. + SM.disableFileContentsOverride(File); + // The FileEntry is a virtual file entry with the size of the contents + // that would override the original contents. Set it to the original's + // size/time. + FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), + StoredSize, StoredTime); + } + + bool IsOutOfDate = false; + + // For an overridden file, there is nothing to validate. + if (!Overridden && (StoredSize != File->getSize() #if !defined(LLVM_ON_WIN32) - // In our regression testing, the Windows file system seems to - // have inconsistent modification times that sometimes - // erroneously trigger this error-handling path. - || StoredTime != File->getModificationTime() + // In our regression testing, the Windows file system seems to + // have inconsistent modification times that sometimes + // erroneously trigger this error-handling path. + || StoredTime != File->getModificationTime() #endif - )) { - if (Complain) { - Error(diag::err_fe_pch_file_modified, Filename, F.FileName); - if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight()) { - Diag(diag::note_module_cache_path) - << PP.getHeaderSearchInfo().getModuleCachePath(); - } + )) { + if (Complain) { + // Build a list of the PCH imports that got us here (in reverse). + SmallVector<ModuleFile *, 4> ImportStack(1, &F); + while (ImportStack.back()->ImportedBy.size() > 0) + ImportStack.push_back(ImportStack.back()->ImportedBy[0]); + + // The top-level PCH is stale. + StringRef TopLevelPCHName(ImportStack.back()->FileName); + Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName); + + // Print the import stack. + if (ImportStack.size() > 1 && !Diags.isDiagnosticInFlight()) { + Diag(diag::note_pch_required_by) + << Filename << ImportStack[0]->FileName; + for (unsigned I = 1; I < ImportStack.size(); ++I) + Diag(diag::note_pch_required_by) + << ImportStack[I-1]->FileName << ImportStack[I]->FileName; } - IsOutOfDate = true; + if (!Diags.isDiagnosticInFlight()) + Diag(diag::note_pch_rebuild_required) << TopLevelPCHName; } - InputFile IF = InputFile(File, Overridden, IsOutOfDate); - - // Note that we've loaded this input file. - F.InputFilesLoaded[ID-1] = IF; - return IF; - } + IsOutOfDate = true; } - return InputFile(); + InputFile IF = InputFile(File, Overridden, IsOutOfDate); + + // Note that we've loaded this input file. + F.InputFilesLoaded[ID-1] = IF; + return IF; } const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { @@ -1751,7 +2174,7 @@ const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { std::string Filename = filenameStrRef; MaybeAddSystemRootToFilename(M, Filename); const FileEntry *File = FileMgr.getFile(Filename); - if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() && + if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() && M.OriginalDir != CurrentDir) { std::string resolved = resolveFileRelativeToOriginalDir(Filename, M.OriginalDir, @@ -1791,6 +2214,7 @@ void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, SmallVectorImpl<ImportedModule> &Loaded, + const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities) { BitstreamCursor &Stream = F.Stream; @@ -1808,20 +2232,54 @@ ASTReader::ReadControlBlock(ModuleFile &F, case llvm::BitstreamEntry::Error: Error("malformed block record in AST file"); return Failure; - case llvm::BitstreamEntry::EndBlock: - // Validate all of the non-system input files. - if (!DisableValidation) { + case llvm::BitstreamEntry::EndBlock: { + // Validate input files. + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + + // All user input files reside at the index range [0, Record[1]), and + // system input files reside at [Record[1], Record[0]). + // Record is the one from INPUT_FILE_OFFSETS. + unsigned NumInputs = Record[0]; + unsigned NumUserInputs = Record[1]; + + if (!DisableValidation && + (ValidateSystemInputs || !HSOpts.ModulesValidateOncePerBuildSession || + F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp)) { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; - // All user input files reside at the index range [0, Record[1]). - // Record is the one from INPUT_FILE_OFFSETS. - for (unsigned I = 0, N = Record[1]; I < N; ++I) { + + // If we are reading a module, we will create a verification timestamp, + // so we verify all input files. Otherwise, verify only user input + // files. + + unsigned N = NumUserInputs; + if (ValidateSystemInputs || + (HSOpts.ModulesValidateOncePerBuildSession && F.Kind == MK_Module)) + N = NumInputs; + + for (unsigned I = 0; I < N; ++I) { InputFile IF = getInputFile(F, I+1, Complain); if (!IF.getFile() || IF.isOutOfDate()) return OutOfDate; } } + + if (Listener) + Listener->visitModuleFile(F.FileName); + + if (Listener && Listener->needsInputFileVisitation()) { + unsigned N = Listener->needsSystemInputFileVisitation() ? NumInputs + : NumUserInputs; + for (unsigned I = 0; I < N; ++I) { + bool IsSystem = I >= NumUserInputs; + InputFileInfo FI = readInputFileInfo(F, I+1); + Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden); + } + } + return Success; - + } + case llvm::BitstreamEntry::SubBlock: switch (Entry.ID) { case INPUT_FILES_BLOCK_ID: @@ -1854,8 +2312,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, case METADATA: { if (Record[0] != VERSION_MAJOR && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old - : diag::warn_pch_version_too_new); + Diag(Record[0] < VERSION_MAJOR? diag::err_pch_version_too_old + : diag::err_pch_version_too_new); return VersionMismatch; } @@ -1871,7 +2329,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, StringRef ASTBranch = Blob; if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch; + Diag(diag::err_pch_different_branch) << ASTBranch << CurBranch; return VersionMismatch; } break; @@ -1916,7 +2374,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; if (Listener && &F == *ModuleMgr.begin() && ParseLanguageOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1925,17 +2383,17 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && ParseTargetOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } case DIAGNOSTIC_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; + bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0; if (Listener && &F == *ModuleMgr.begin() && ParseDiagnosticOptions(Record, Complain, *Listener) && !DisableValidation) - return ConfigurationMismatch; + return OutOfDate; break; } @@ -1943,7 +2401,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && ParseFileSystemOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1952,7 +2410,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && ParseHeaderSearchOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1962,7 +2420,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, if (Listener && &F == *ModuleMgr.begin() && ParsePreprocessorOptions(Record, Complain, *Listener, SuggestedPredefines) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1982,6 +2440,49 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.OriginalDir = Blob; break; + case MODULE_NAME: + F.ModuleName = Blob; + if (Listener) + Listener->ReadModuleName(F.ModuleName); + break; + + case MODULE_MAP_FILE: + F.ModuleMapPath = Blob; + + // Try to resolve ModuleName in the current header search context and + // verify that it is found in the same module map file as we saved. If the + // top-level AST file is a main file, skip this check because there is no + // usable header search context. + assert(!F.ModuleName.empty() && + "MODULE_NAME should come before MOUDLE_MAP_FILE"); + if (F.Kind == MK_Module && + (*ModuleMgr.begin())->Kind != MK_MainFile) { + Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + if (!M) { + assert(ImportedBy && "top-level import should be verified"); + if ((ClientLoadCapabilities & ARR_Missing) == 0) + Diag(diag::err_imported_module_not_found) + << F.ModuleName << ImportedBy->FileName; + return Missing; + } + + const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath); + if (StoredModMap == nullptr || StoredModMap != M->ModuleMap) { + assert(M->ModuleMap && "found module is missing module map file"); + assert(M->Name == F.ModuleName && "found module with different name"); + assert(ImportedBy && "top-level import should be verified"); + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_imported_module_modmap_changed) + << F.ModuleName << ImportedBy->FileName + << M->ModuleMap->getName() << F.ModuleMapPath; + return OutOfDate; + } + } + + if (Listener) + Listener->ReadModuleMapFile(F.ModuleMapPath); + break; + case INPUT_FILE_OFFSETS: F.InputFileOffsets = (const uint32_t *)Blob.data(); F.InputFilesLoaded.resize(Record[0]); @@ -1990,12 +2491,13 @@ ASTReader::ReadControlBlock(ModuleFile &F, } } -bool ASTReader::ReadASTBlock(ModuleFile &F) { +ASTReader::ASTReadResult +ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { BitstreamCursor &Stream = F.Stream; if (Stream.EnterSubBlock(AST_BLOCK_ID)) { Error("malformed block record in AST file"); - return true; + return Failure; } // Read all of the records and blocks for the AST file. @@ -2006,7 +2508,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { switch (Entry.Kind) { case llvm::BitstreamEntry::Error: Error("error at end of module block in AST file"); - return true; + return Failure; case llvm::BitstreamEntry::EndBlock: { // Outside of C++, we do not store a lookup map for the translation unit. // Instead, mark it as needing a lookup map to be built if this module @@ -2018,7 +2520,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { !getContext().getLangOpts().CPlusPlus) DC->setMustBuildLookupTable(); - return false; + return Success; } case llvm::BitstreamEntry::SubBlock: switch (Entry.ID) { @@ -2032,17 +2534,10 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Read the abbrevs. ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) { Error("malformed block record in AST file"); - return true; - } - break; - - case DECL_UPDATES_BLOCK_ID: - if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return true; + return Failure; } break; - + case PREPROCESSOR_BLOCK_ID: F.MacroCursor = Stream; if (!PP.getExternalSource()) @@ -2051,7 +2546,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (Stream.SkipBlock() || ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) { Error("malformed block record in AST file"); - return true; + return Failure; } F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo(); break; @@ -2062,7 +2557,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { ReadBlockAbbrevs(F.PreprocessorDetailCursor, PREPROCESSOR_DETAIL_BLOCK_ID)) { Error("malformed preprocessor detail record in AST file"); - return true; + return Failure; } F.PreprocessorDetailStartOffset = F.PreprocessorDetailCursor.GetCurrentBitNo(); @@ -2075,12 +2570,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case SOURCE_MANAGER_BLOCK_ID: if (ReadSourceManagerBlock(F)) - return true; + return Failure; break; case SUBMODULE_BLOCK_ID: - if (ReadSubmoduleBlock(F)) - return true; + if (ASTReadResult Result = ReadSubmoduleBlock(F, ClientLoadCapabilities)) + return Result; break; case COMMENTS_BLOCK_ID: { @@ -2088,7 +2583,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (Stream.SkipBlock() || ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) { Error("malformed comments block in AST file"); - return true; + return Failure; } CommentsCursors.push_back(std::make_pair(C, &F)); break; @@ -2097,7 +2592,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { default: if (Stream.SkipBlock()) { Error("malformed block record in AST file"); - return true; + return Failure; } break; } @@ -2118,7 +2613,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case TYPE_OFFSET: { if (F.LocalNumTypes != 0) { Error("duplicate TYPE_OFFSET record in AST file"); - return true; + return Failure; } F.TypeOffsets = (const uint32_t *)Blob.data(); F.LocalNumTypes = Record[0]; @@ -2142,7 +2637,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case DECL_OFFSET: { if (F.LocalNumDecls != 0) { Error("duplicate DECL_OFFSET record in AST file"); - return true; + return Failure; } F.DeclOffsets = (const DeclOffset *)Blob.data(); F.LocalNumDecls = Record[0]; @@ -2183,14 +2678,18 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { unsigned Idx = 0; serialization::DeclID ID = ReadDeclID(F, Record, Idx); ASTDeclContextNameLookupTable *Table = - ASTDeclContextNameLookupTable::Create( - (const unsigned char *)Blob.data() + Record[Idx++], - (const unsigned char *)Blob.data(), - ASTDeclContextNameLookupTrait(*this, F)); - if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU? - DeclContext *TU = Context.getTranslationUnitDecl(); - F.DeclContextInfos[TU].NameLookupTableData = Table; - TU->setHasExternalVisibleStorage(true); + ASTDeclContextNameLookupTable::Create( + (const unsigned char *)Blob.data() + Record[Idx++], + (const unsigned char *)Blob.data() + sizeof(uint32_t), + (const unsigned char *)Blob.data(), + ASTDeclContextNameLookupTrait(*this, F)); + if (Decl *D = GetExistingDecl(ID)) { + auto *DC = cast<DeclContext>(D); + DC->getPrimaryContext()->setHasExternalVisibleStorage(true); + auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData; + // FIXME: There should never be an existing lookup table. + delete LookupTable; + LookupTable = Table; } else PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F)); break; @@ -2199,11 +2698,11 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case IDENTIFIER_TABLE: F.IdentifierTableData = Blob.data(); if (Record[0]) { - F.IdentifierLookupTable - = ASTIdentifierLookupTable::Create( - (const unsigned char *)F.IdentifierTableData + Record[0], - (const unsigned char *)F.IdentifierTableData, - ASTIdentifierLookupTrait(*this, F)); + F.IdentifierLookupTable = ASTIdentifierLookupTable::Create( + (const unsigned char *)F.IdentifierTableData + Record[0], + (const unsigned char *)F.IdentifierTableData + sizeof(uint32_t), + (const unsigned char *)F.IdentifierTableData, + ASTIdentifierLookupTrait(*this, F)); PP.getIdentifierTable().setExternalIdentifierLookup(this); } @@ -2212,7 +2711,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case IDENTIFIER_OFFSET: { if (F.LocalNumIdentifiers != 0) { Error("duplicate IDENTIFIER_OFFSET record in AST file"); - return true; + return Failure; } F.IdentifierOffsets = (const uint32_t *)Blob.data(); F.LocalNumIdentifiers = Record[0]; @@ -2237,9 +2736,9 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; } - case EXTERNAL_DEFINITIONS: + case EAGERLY_DESERIALIZED_DECLS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I])); + EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); break; case SPECIAL_TYPES: @@ -2251,7 +2750,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (SpecialTypes.size() != Record.size()) { Error("invalid special-types record"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; ++I) { @@ -2283,7 +2782,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case WEAK_UNDECLARED_IDENTIFIERS: if (Record.size() % 4 != 0) { Error("invalid weak identifiers record"); - return true; + return Failure; } // FIXME: Ignore weak undeclared identifiers from non-original PCH @@ -2365,7 +2864,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { F.SLocEntryOffsets = (const uint32_t *)Blob.data(); F.LocalNumSLocEntries = Record[0]; unsigned SLocSpaceSize = Record[1]; - llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = + std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, SLocSpaceSize); // Make our entry in the range map. BaseID is negative and growing, so @@ -2384,9 +2883,9 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Initialize the remapping table. // Invalid stays invalid. - F.SLocRemap.insert(std::make_pair(0U, 0)); + F.SLocRemap.insertOrReplace(std::make_pair(0U, 0)); // This module. Base was 2 when being compiled. - F.SLocRemap.insert(std::make_pair(2U, + F.SLocRemap.insertOrReplace(std::make_pair(2U, static_cast<int>(F.SLocEntryBaseOffset - 2))); TotalNumSLocEntries += F.LocalNumSLocEntries; @@ -2397,7 +2896,13 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Additional remapping information. const unsigned char *Data = (const unsigned char*)Blob.data(); const unsigned char *DataEnd = Data + Blob.size(); - + + // If we see this entry before SOURCE_LOCATION_OFFSETS, add placeholders. + if (F.SLocRemap.find(0) == F.SLocRemap.end()) { + F.SLocRemap.insert(std::make_pair(0U, 0)); + F.SLocRemap.insert(std::make_pair(2U, 1)); + } + // Continuous range maps we may be updating in our module. ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder @@ -2414,24 +2919,33 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap); while(Data < DataEnd) { - uint16_t Len = io::ReadUnalignedLE16(Data); + using namespace llvm::support; + uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data); StringRef Name = StringRef((const char*)Data, Len); Data += Len; ModuleFile *OM = ModuleMgr.lookup(Name); if (!OM) { Error("SourceLocation remap refers to unknown module"); - return true; + return Failure; } - uint32_t SLocOffset = io::ReadUnalignedLE32(Data); - uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data); - uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data); - uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data); - uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data); - uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data); - uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data); - uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data); - + uint32_t SLocOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t IdentifierIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t MacroIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t PreprocessedEntityIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t SubmoduleIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t SelectorIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t DeclIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t TypeIndexOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + // Source location offset is mapped to OM->SLocEntryBaseOffset. SLocRemap.insert(std::make_pair(SLocOffset, static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset))); @@ -2461,7 +2975,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case SOURCE_MANAGER_LINE_TABLE: if (ParseLineTable(F, Record)) - return true; + return Failure; break; case SOURCE_LOCATION_PRELOADS: { @@ -2469,7 +2983,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // which is based off F.SLocEntryBaseID. if (!F.PreloadSLocEntries.empty()) { Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file"); - return true; + return Failure; } F.PreloadSLocEntries.swap(Record); @@ -2484,7 +2998,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case VTABLE_USES: if (Record.size() % 3 != 0) { Error("Invalid VTABLE_USES record"); - return true; + return Failure; } // Later tables overwrite earlier ones. @@ -2508,12 +3022,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case PENDING_IMPLICIT_INSTANTIATIONS: if (PendingInstantiations.size() % 2 != 0) { Error("Invalid existing PendingInstantiations"); - return true; + return Failure; } if (Record.size() % 2 != 0) { Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { @@ -2526,7 +3040,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case SEMA_DECL_REFS: if (Record.size() != 2) { Error("Invalid SEMA_DECL_REFS block"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; ++I) SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); @@ -2567,18 +3081,24 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case DECL_UPDATE_OFFSETS: { if (Record.size() % 2 != 0) { Error("invalid DECL_UPDATE_OFFSETS block in AST file"); - return true; + return Failure; + } + for (unsigned I = 0, N = Record.size(); I != N; I += 2) { + GlobalDeclID ID = getGlobalDeclID(F, Record[I]); + DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1])); + + // If we've already loaded the decl, perform the updates when we finish + // loading this block. + if (Decl *D = GetExistingDecl(ID)) + PendingUpdateRecords.push_back(std::make_pair(ID, D)); } - for (unsigned I = 0, N = Record.size(); I != N; I += 2) - DeclUpdateOffsets[getGlobalDeclID(F, Record[I])] - .push_back(std::make_pair(&F, Record[I+1])); break; } case DECL_REPLACEMENTS: { if (Record.size() % 3 != 0) { Error("invalid DECL_REPLACEMENTS block in AST file"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; I += 3) ReplacedDecls[getGlobalDeclID(F, Record[I])] @@ -2589,7 +3109,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case OBJC_CATEGORIES_MAP: { if (F.LocalNumObjCCategoriesInMap != 0) { Error("duplicate OBJC_CATEGORIES_MAP record in AST file"); - return true; + return Failure; } F.LocalNumObjCCategoriesInMap = Record[0]; @@ -2604,7 +3124,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case CXX_BASE_SPECIFIER_OFFSETS: { if (F.LocalNumCXXBaseSpecifiers != 0) { Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file"); - return true; + return Failure; } F.LocalNumCXXBaseSpecifiers = Record[0]; @@ -2671,12 +3191,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case UNDEFINED_BUT_USED: if (UndefinedButUsed.size() % 2 != 0) { Error("Invalid existing UndefinedButUsed"); - return true; + return Failure; } if (Record.size() % 2 != 0) { Error("invalid undefined-but-used record"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++])); @@ -2690,9 +3210,11 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // If we aren't loading a module (which has its own exports), make // all of the imported modules visible. // FIXME: Deal with macros-only imports. - for (unsigned I = 0, N = Record.size(); I != N; ++I) { - if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I])) - ImportedModules.push_back(GlobalID); + for (unsigned I = 0, N = Record.size(); I != N; /**/) { + unsigned GlobalID = getGlobalSubmoduleID(F, Record[I++]); + SourceLocation Loc = ReadSourceLocation(F, Record, I); + if (GlobalID) + ImportedModules.push_back(ImportedSubmodule(GlobalID, Loc)); } } break; @@ -2706,7 +3228,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case LOCAL_REDECLARATIONS_MAP: { if (F.LocalNumRedeclarationsInMap != 0) { Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file"); - return true; + return Failure; } F.LocalNumRedeclarationsInMap = Record[0]; @@ -2727,7 +3249,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case MACRO_OFFSET: { if (F.LocalNumMacros != 0) { Error("duplicate MACRO_OFFSET record in AST file"); - return true; + return Failure; } F.MacroOffsets = (const uint32_t *)Blob.data(); F.LocalNumMacros = Record[0]; @@ -2757,6 +3279,14 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { LateParsedTemplates.append(Record.begin(), Record.end()); break; } + + case OPTIMIZE_PRAGMA_OPTIONS: + if (Record.size() != 1) { + Error("invalid pragma optimize record"); + return Failure; + } + OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]); + break; } } } @@ -2790,31 +3320,27 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { } } -void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) { - for (unsigned I = 0, N = Names.size(); I != N; ++I) { - switch (Names[I].getKind()) { - case HiddenName::Declaration: { - Decl *D = Names[I].getDecl(); - bool wasHidden = D->Hidden; - D->Hidden = false; +void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner, + bool FromFinalization) { + // FIXME: Only do this if Owner->NameVisibility == AllVisible. + for (Decl *D : Names.HiddenDecls) { + bool wasHidden = D->Hidden; + D->Hidden = false; - if (wasHidden && SemaObj) { - if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { - moveMethodToBackOfGlobalList(*SemaObj, Method); - } + if (wasHidden && SemaObj) { + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { + moveMethodToBackOfGlobalList(*SemaObj, Method); } - break; - } - case HiddenName::MacroVisibility: { - std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro(); - installImportedMacro(Macro.first, Macro.second, Owner); - break; - } } } + + assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) && + "nothing to make visible?"); + for (const auto &Macro : Names.HiddenMacros) + installImportedMacro(Macro.first, Macro.second, Owner, FromFinalization); } -void ASTReader::makeModuleVisible(Module *Mod, +void ASTReader::makeModuleVisible(Module *Mod, Module::NameVisibilityKind NameVisibility, SourceLocation ImportLoc, bool Complain) { @@ -2829,21 +3355,28 @@ void ASTReader::makeModuleVisible(Module *Mod, // there is nothing more to do. continue; } - + if (!Mod->isAvailable()) { // Modules that aren't available cannot be made visible. continue; } // Update the module's name visibility. + if (NameVisibility >= Module::MacrosVisible && + Mod->NameVisibility < Module::MacrosVisible) + Mod->MacroVisibilityLoc = ImportLoc; Mod->NameVisibility = NameVisibility; - + // If we've already deserialized any names from this module, // mark them as visible. HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod); if (Hidden != HiddenNamesMap.end()) { - makeNamesVisible(Hidden->second, Hidden->first); + auto HiddenNames = std::move(*Hidden); HiddenNamesMap.erase(Hidden); + makeNamesVisible(HiddenNames.second, HiddenNames.first, + /*FromFinalization*/false); + assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() && + "making names visible added hidden names"); } // Push any exported modules onto the stack to be marked as visible. @@ -2899,6 +3432,17 @@ bool ASTReader::isGlobalIndexUnavailable() const { !hasGlobalIndex() && TriedLoadingGlobalIndex; } +static void updateModuleTimestamp(ModuleFile &MF) { + // Overwrite the timestamp file contents so that file's mtime changes. + std::string TimestampFilename = MF.getTimestampFilename(); + std::string ErrorInfo; + llvm::raw_fd_ostream OS(TimestampFilename.c_str(), ErrorInfo, + llvm::sys::fs::F_Text); + if (!ErrorInfo.empty()) + return; + OS << "Timestamp file\n"; +} + ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type, SourceLocation ImportLoc, @@ -2906,13 +3450,16 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, llvm::SaveAndRestore<SourceLocation> SetCurImportLocRAII(CurrentImportLoc, ImportLoc); + // Defer any pending actions until we get to the end of reading the AST file. + Deserializing AnASTFile(this); + // Bump the generation number. - unsigned PreviousGeneration = CurrentGeneration++; + unsigned PreviousGeneration = incrementGeneration(Context); unsigned NumModules = ModuleMgr.size(); SmallVector<ImportedModule, 4> Loaded; switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc, - /*ImportedBy=*/0, Loaded, + /*ImportedBy=*/nullptr, Loaded, 0, 0, ClientLoadCapabilities)) { case Failure: @@ -2920,18 +3467,23 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, case OutOfDate: case VersionMismatch: case ConfigurationMismatch: - case HadErrors: + case HadErrors: { + llvm::SmallPtrSet<ModuleFile *, 4> LoadedSet; + for (const ImportedModule &IM : Loaded) + LoadedSet.insert(IM.Mod); + ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(), + LoadedSet, Context.getLangOpts().Modules ? &PP.getHeaderSearchInfo().getModuleMap() - : 0); + : nullptr); // If we find that any modules are unusable, the global index is going // to be out-of-date. Just remove it. GlobalIndex.reset(); - ModuleMgr.setGlobalIndex(0); + ModuleMgr.setGlobalIndex(nullptr); return ReadResult; - + } case Success: break; } @@ -2945,8 +3497,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleFile &F = *M->Mod; // Read the AST block. - if (ReadASTBlock(F)) - return Failure; + if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities)) + return Result; // Once read, set the ModuleFile bit base offset and update the size in // bits of all files we've seen. @@ -3057,6 +3609,21 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, PreviousGeneration); } + if (PP.getHeaderSearchInfo() + .getHeaderSearchOpts() + .ModulesValidateOncePerBuildSession) { + // Now we are certain that the module and all modules it depends on are + // up to date. Create or update timestamp files for modules that are + // located in the module cache (not for PCH files that could be anywhere + // in the filesystem). + for (unsigned I = 0, N = Loaded.size(); I != N; ++I) { + ImportedModule &M = Loaded[I]; + if (M.Mod->Kind == MK_Module) { + updateModuleTimestamp(*M.Mod); + } + } + } + return Success; } @@ -3072,7 +3639,7 @@ ASTReader::ReadASTCore(StringRef FileName, std::string ErrorStr; ModuleManager::AddModuleResult AddResult = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, - CurrentGeneration, ExpectedSize, ExpectedModTime, + getGeneration(), ExpectedSize, ExpectedModTime, M, ErrorStr); switch (AddResult) { @@ -3162,7 +3729,7 @@ ASTReader::ReadASTCore(StringRef FileName, break; case CONTROL_BLOCK_ID: HaveReadControlBlock = true; - switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) { + switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) { case Success: break; @@ -3177,7 +3744,7 @@ ASTReader::ReadASTCore(StringRef FileName, case AST_BLOCK_ID: if (!HaveReadControlBlock) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(diag::warn_pch_version_too_old); + Diag(diag::err_pch_version_too_old); return VersionMismatch; } @@ -3203,11 +3770,6 @@ void ASTReader::InitializeContext() { DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, Context.getTranslationUnitDecl()); - // Make sure we load the declaration update records for the translation unit, - // if there are any. - loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID, - Context.getTranslationUnitDecl()); - // FIXME: Find a better way to deal with collisions between these // built-in types. Right now, we just ignore the problem. @@ -3323,24 +3885,26 @@ void ASTReader::InitializeContext() { Context.setcudaConfigureCallDecl( cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0]))); } - + // Re-export any modules that were imported by a non-module AST file. - for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) { - if (Module *Imported = getSubmodule(ImportedModules[I])) + // FIXME: This does not make macro-only imports visible again. It also doesn't + // make #includes mapped to module imports visible. + for (auto &Import : ImportedModules) { + if (Module *Imported = getSubmodule(Import.ID)) makeModuleVisible(Imported, Module::AllVisible, - /*ImportLoc=*/SourceLocation(), + /*ImportLoc=*/Import.ImportLoc, /*Complain=*/false); } ImportedModules.clear(); } void ASTReader::finalizeForWriting() { - for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(), - HiddenEnd = HiddenNamesMap.end(); - Hidden != HiddenEnd; ++Hidden) { - makeNamesVisible(Hidden->second, Hidden->first); + while (!HiddenNamesMap.empty()) { + auto HiddenNames = std::move(*HiddenNamesMap.begin()); + HiddenNamesMap.erase(HiddenNamesMap.begin()); + makeNamesVisible(HiddenNames.second, HiddenNames.first, + /*FromFinalization*/true); } - HiddenNamesMap.clear(); } /// \brief Given a cursor at the start of an AST file, scan ahead and drop the @@ -3381,7 +3945,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, DiagnosticsEngine &Diags) { // Open the AST file. std::string ErrStr; - OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr)); if (!Buffer) { Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr; @@ -3448,18 +4012,18 @@ namespace { { } - virtual bool ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain) { - return checkLanguageOptions(ExistingLangOpts, LangOpts, 0); + bool ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) override { + return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr); } - virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain) { - return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0); + bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) override { + return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr); } - virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, - bool Complain, - std::string &SuggestedPredefines) { - return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr, + bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines) override { + return checkPreprocessorOptions(ExistingPPOpts, PPOpts, nullptr, FileMgr, SuggestedPredefines, ExistingLangOpts); } }; @@ -3470,7 +4034,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, ASTReaderListener &Listener) { // Open the AST file. std::string ErrStr; - OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr)); if (!Buffer) { return true; @@ -3496,6 +4060,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, return true; bool NeedsInputFiles = Listener.needsInputFileVisitation(); + bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation(); BitstreamCursor InputFilesCursor; if (NeedsInputFiles) { InputFilesCursor = Stream; @@ -3539,6 +4104,12 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, break; } + case MODULE_NAME: + Listener.ReadModuleName(Blob); + break; + case MODULE_MAP_FILE: + Listener.ReadModuleMapFile(Blob); + break; case LANGUAGE_OPTIONS: if (ParseLanguageOptions(Record, false, Listener)) return true; @@ -3582,6 +4153,10 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, for (unsigned I = 0; I != NumInputFiles; ++I) { // Go find this input file. bool isSystemFile = I >= NumUserFiles; + + if (isSystemFile && !NeedsSystemInputFiles) + break; // the rest are system input files + BitstreamCursor &Cursor = InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(InputFileOffs[I]); @@ -3592,7 +4167,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, bool shouldContinue = false; switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { case INPUT_FILE: - shouldContinue = Listener.visitInputFile(Blob, isSystemFile); + bool Overridden = static_cast<bool>(Record[3]); + shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden); break; } if (!shouldContinue) @@ -3618,16 +4194,17 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename, return !readASTFileControlBlock(Filename, FileMgr, validator); } -bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { +ASTReader::ASTReadResult +ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Enter the submodule block. if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) { Error("malformed submodule block record in AST file"); - return true; + return Failure; } ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); bool First = true; - Module *CurrentModule = 0; + Module *CurrentModule = nullptr; RecordData Record; while (true) { llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks(); @@ -3636,9 +4213,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: Error("malformed block record in AST file"); - return true; + return Failure; case llvm::BitstreamEntry::EndBlock: - return false; + return Success; case llvm::BitstreamEntry::Record: // The interesting case. break; @@ -3654,39 +4231,47 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_DEFINITION: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (Record.size() < 8) { Error("malformed module definition"); - return true; + return Failure; } StringRef Name = Blob; - SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]); - SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]); - bool IsFramework = Record[2]; - bool IsExplicit = Record[3]; - bool IsSystem = Record[4]; - bool InferSubmodules = Record[5]; - bool InferExplicitSubmodules = Record[6]; - bool InferExportWildcard = Record[7]; - bool ConfigMacrosExhaustive = Record[8]; - - Module *ParentModule = 0; - if (Parent) + unsigned Idx = 0; + SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]); + SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]); + bool IsFramework = Record[Idx++]; + bool IsExplicit = Record[Idx++]; + bool IsSystem = Record[Idx++]; + bool IsExternC = Record[Idx++]; + bool InferSubmodules = Record[Idx++]; + bool InferExplicitSubmodules = Record[Idx++]; + bool InferExportWildcard = Record[Idx++]; + bool ConfigMacrosExhaustive = Record[Idx++]; + + Module *ParentModule = nullptr; + const FileEntry *ModuleMap = nullptr; + if (Parent) { ParentModule = getSubmodule(Parent); - + ModuleMap = ParentModule->ModuleMap; + } + + if (!F.ModuleMapPath.empty()) + ModuleMap = FileMgr.getFile(F.ModuleMapPath); + // Retrieve this (sub)module from the module map, creating it if // necessary. - CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, + CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, ModuleMap, IsFramework, IsExplicit).first; SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; if (GlobalIndex >= SubmodulesLoaded.size() || SubmodulesLoaded[GlobalIndex]) { Error("too many submodules"); - return true; + return Failure; } if (!ParentModule) { @@ -3698,15 +4283,16 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { << CurFile->getName() << F.File->getName(); } - return true; + return Failure; } } CurrentModule->setASTFile(F.File); } - + CurrentModule->IsFromModuleFile = true; CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; + CurrentModule->IsExternC = IsExternC; CurrentModule->InferSubmodules = InferSubmodules; CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; CurrentModule->InferExportWildcard = InferExportWildcard; @@ -3727,7 +4313,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_UMBRELLA_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3737,8 +4323,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule->getUmbrellaHeader()) ModMap.setUmbrellaHeader(CurrentModule, Umbrella); else if (CurrentModule->getUmbrellaHeader() != Umbrella) { - Error("mismatched umbrella headers in submodule"); - return true; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Error("mismatched umbrella headers in submodule"); + return OutOfDate; } } break; @@ -3747,7 +4334,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3762,7 +4349,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_EXCLUDED_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3777,7 +4364,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_PRIVATE_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3792,7 +4379,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_TOPHEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3805,7 +4392,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_UMBRELLA_DIR: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3816,8 +4403,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule->getUmbrellaDir()) ModMap.setUmbrellaDir(CurrentModule, Umbrella); else if (CurrentModule->getUmbrellaDir() != Umbrella) { - Error("mismatched umbrella directories in submodule"); - return true; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Error("mismatched umbrella directories in submodule"); + return OutOfDate; } } break; @@ -3826,7 +4414,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_METADATA: { if (!First) { Error("submodule metadata record not at beginning of block"); - return true; + return Failure; } First = false; @@ -3852,7 +4440,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_IMPORTS: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3873,7 +4461,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_EXPORTS: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3897,7 +4485,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_REQUIRES: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3911,7 +4499,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_LINK_LIBRARY: if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3924,7 +4512,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_CONFIG_MACRO: if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3936,7 +4524,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_CONFLICT: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -4004,8 +4592,6 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record, TargetOpts.Triple = ReadString(Record, Idx); TargetOpts.CPU = ReadString(Record, Idx); TargetOpts.ABI = ReadString(Record, Idx); - TargetOpts.CXXABI = ReadString(Record, Idx); - TargetOpts.LinkerVersion = ReadString(Record, Idx); for (unsigned N = Record[Idx++]; N; --N) { TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx)); } @@ -4018,16 +4604,17 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record, bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain, ASTReaderListener &Listener) { - DiagnosticOptions DiagOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions); unsigned Idx = 0; -#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++]; +#define DIAGOPT(Name, Bits, Default) DiagOpts->Name = Record[Idx++]; #define ENUM_DIAGOPT(Name, Type, Bits, Default) \ - DiagOpts.set##Name(static_cast<Type>(Record[Idx++])); + DiagOpts->set##Name(static_cast<Type>(Record[Idx++])); #include "clang/Basic/DiagnosticOptions.def" - for (unsigned N = Record[Idx++]; N; --N) { - DiagOpts.Warnings.push_back(ReadString(Record, Idx)); - } + for (unsigned N = Record[Idx++]; N; --N) + DiagOpts->Warnings.push_back(ReadString(Record, Idx)); + for (unsigned N = Record[Idx++]; N; --N) + DiagOpts->Remarks.push_back(ReadString(Record, Idx)); return Listener.ReadDiagnosticOptions(DiagOpts, Complain); } @@ -4068,6 +4655,7 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, HSOpts.ResourceDir = ReadString(Record, Idx); HSOpts.ModuleCachePath = ReadString(Record, Idx); + HSOpts.ModuleUserBuildPath = ReadString(Record, Idx); HSOpts.DisableModuleHash = Record[Idx++]; HSOpts.UseBuiltinIncludes = Record[Idx++]; HSOpts.UseStandardSystemIncludes = Record[Idx++]; @@ -4149,7 +4737,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { if (!PP.getPreprocessingRecord()) { Error("no preprocessing record"); - return 0; + return nullptr; } SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); @@ -4158,7 +4746,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { llvm::BitstreamEntry Entry = M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); if (Entry.Kind != llvm::BitstreamEntry::Record) - return 0; + return nullptr; // Read the record. SourceRange Range(ReadSourceLocation(M, PPOffs.Begin), @@ -4172,8 +4760,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { switch (RecType) { case PPD_MACRO_EXPANSION: { bool isBuiltin = Record[0]; - IdentifierInfo *Name = 0; - MacroDefinition *Def = 0; + IdentifierInfo *Name = nullptr; + MacroDefinition *Def = nullptr; if (isBuiltin) Name = getLocalIdentifier(M, Record[1]); else { @@ -4207,7 +4795,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { case PPD_INCLUSION_DIRECTIVE: { const char *FullFileNameStart = Blob.data() + Record[0]; StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]); - const FileEntry *File = 0; + const FileEntry *File = nullptr; if (!FullFileName.empty()) File = PP.getFileManager().getFile(FullFileName); @@ -4276,15 +4864,13 @@ struct PPEntityComp { } -/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc. -PreprocessedEntityID -ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { - if (SourceMgr.isLocalSourceLocation(BLoc)) +PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc, + bool EndsAfter) const { + if (SourceMgr.isLocalSourceLocation(Loc)) return getTotalNumPreprocessedEntities(); - GlobalSLocOffsetMapType::const_iterator - SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - - BLoc.getOffset() - 1); + GlobalSLocOffsetMapType::const_iterator SLocMapI = GlobalSLocOffsetMap.find( + SourceManager::MaxLoadedOffset - Loc.getOffset() - 1); assert(SLocMapI != GlobalSLocOffsetMap.end() && "Corrupted global sloc offset map"); @@ -4301,21 +4887,26 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { pp_iterator First = pp_begin; pp_iterator PPI; - // Do a binary search manually instead of using std::lower_bound because - // The end locations of entities may be unordered (when a macro expansion - // is inside another macro argument), but for this case it is not important - // whether we get the first macro expansion or its containing macro. - while (Count > 0) { - Half = Count/2; - PPI = First; - std::advance(PPI, Half); - if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End), - BLoc)){ - First = PPI; - ++First; - Count = Count - Half - 1; - } else - Count = Half; + if (EndsAfter) { + PPI = std::upper_bound(pp_begin, pp_end, Loc, + PPEntityComp<&PPEntityOffset::Begin>(*this, M)); + } else { + // Do a binary search manually instead of using std::lower_bound because + // The end locations of entities may be unordered (when a macro expansion + // is inside another macro argument), but for this case it is not important + // whether we get the first macro expansion or its containing macro. + while (Count > 0) { + Half = Count / 2; + PPI = First; + std::advance(PPI, Half); + if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End), + Loc)) { + First = PPI; + ++First; + Count = Count - Half - 1; + } else + Count = Half; + } } if (PPI == pp_end) @@ -4324,35 +4915,6 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { return M.BasePreprocessedEntityID + (PPI - pp_begin); } -/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc. -PreprocessedEntityID -ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const { - if (SourceMgr.isLocalSourceLocation(ELoc)) - return getTotalNumPreprocessedEntities(); - - GlobalSLocOffsetMapType::const_iterator - SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - - ELoc.getOffset() - 1); - assert(SLocMapI != GlobalSLocOffsetMap.end() && - "Corrupted global sloc offset map"); - - if (SLocMapI->second->NumPreprocessedEntities == 0) - return findNextPreprocessedEntity(SLocMapI); - - ModuleFile &M = *SLocMapI->second; - typedef const PPEntityOffset *pp_iterator; - pp_iterator pp_begin = M.PreprocessedEntityOffsets; - pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; - pp_iterator PPI = - std::upper_bound(pp_begin, pp_end, ELoc, - PPEntityComp<&PPEntityOffset::Begin>(*this, M)); - - if (PPI == pp_end) - return findNextPreprocessedEntity(SLocMapI); - - return M.BasePreprocessedEntityID + (PPI - pp_begin); -} - /// \brief Returns a pair of [Begin, End) indices of preallocated /// preprocessed entities that \arg Range encompasses. std::pair<unsigned, unsigned> @@ -4361,8 +4923,9 @@ std::pair<unsigned, unsigned> return std::make_pair(0,0); assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); - PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin()); - PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd()); + PreprocessedEntityID BeginID = + findPreprocessedEntity(Range.getBegin(), false); + PreprocessedEntityID EndID = findPreprocessedEntity(Range.getEnd(), true); return std::make_pair(BeginID, EndID); } @@ -4468,9 +5031,9 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { if (DiagID == (unsigned)-1) { break; // no more diag/map pairs for this location. } - diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++]; - DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc); - Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo); + diag::Severity Map = (diag::Severity)F.PragmaDiagMappings[Idx++]; + DiagnosticMapping Mapping = Diag.makeUserMapping(Map, Loc); + Diag.GetCurDiagState()->setMapping(DiagID, Mapping); } } } @@ -4548,6 +5111,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return DT; } + case TYPE_ADJUSTED: { + if (Record.size() != 2) { + Error("Incorrect encoding of adjusted type"); + return QualType(); + } + QualType OriginalTy = readType(*Loc.F, Record, Idx); + QualType AdjustedTy = readType(*Loc.F, Record, Idx); + return Context.getAdjustedType(OriginalTy, AdjustedTy); + } + case TYPE_BLOCK_POINTER: { if (Record.size() != 1) { Error("Incorrect encoding of block pointer type"); @@ -4671,23 +5244,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) { EPI.HasTrailingReturn = Record[Idx++]; EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]); - ExceptionSpecificationType EST = - static_cast<ExceptionSpecificationType>(Record[Idx++]); - EPI.ExceptionSpecType = EST; - SmallVector<QualType, 2> Exceptions; - if (EST == EST_Dynamic) { - EPI.NumExceptions = Record[Idx++]; - for (unsigned I = 0; I != EPI.NumExceptions; ++I) - Exceptions.push_back(readType(*Loc.F, Record, Idx)); - EPI.Exceptions = Exceptions.data(); - } else if (EST == EST_ComputedNoexcept) { - EPI.NoexceptExpr = ReadExpr(*Loc.F); - } else if (EST == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); - EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); - } else if (EST == EST_Unevaluated) { - EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); - } + SmallVector<QualType, 8> ExceptionStorage; + readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx); return Context.getFunctionType(ResultType, ParamTypes, EPI); } @@ -4837,9 +5395,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) { unsigned Idx = 0; QualType Parm = readType(*Loc.F, Record, Idx); QualType Replacement = readType(*Loc.F, Record, Idx); - return - Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), - Replacement); + return Context.getSubstTemplateTypeParmType( + cast<TemplateTypeParmType>(Parm), + Context.getCanonicalType(Replacement)); } case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: { @@ -4856,8 +5414,14 @@ QualType ASTReader::readTypeRecord(unsigned Index) { QualType TST = readType(*Loc.F, Record, Idx); // probably derivable // FIXME: ASTContext::getInjectedClassNameType is not currently suitable // for AST reading, too much interdependencies. - return - QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0); + const Type *T; + if (const Type *Existing = D->getTypeForDecl()) + T = Existing; + else if (auto *Prev = D->getPreviousDecl()) + T = Prev->getTypeForDecl(); + else + T = new (Context, TypeAlignment) InjectedClassNameType(D, TST); + return QualType(T, 0); } case TYPE_TEMPLATE_TYPE_PARM: { @@ -4942,6 +5506,29 @@ QualType ASTReader::readTypeRecord(unsigned Index) { llvm_unreachable("Invalid TypeCode!"); } +void ASTReader::readExceptionSpec(ModuleFile &ModuleFile, + SmallVectorImpl<QualType> &Exceptions, + FunctionProtoType::ExtProtoInfo &EPI, + const RecordData &Record, unsigned &Idx) { + ExceptionSpecificationType EST = + static_cast<ExceptionSpecificationType>(Record[Idx++]); + EPI.ExceptionSpecType = EST; + if (EST == EST_Dynamic) { + EPI.NumExceptions = Record[Idx++]; + for (unsigned I = 0; I != EPI.NumExceptions; ++I) + Exceptions.push_back(readType(ModuleFile, Record, Idx)); + EPI.Exceptions = Exceptions.data(); + } else if (EST == EST_ComputedNoexcept) { + EPI.NoexceptExpr = ReadExpr(ModuleFile); + } else if (EST == EST_Uninstantiated) { + EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + EPI.ExceptionSpecTemplate = + ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + } else if (EST == EST_Unevaluated) { + EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + } +} + class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { ASTReader &Reader; ModuleFile &F; @@ -4997,6 +5584,9 @@ void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) { // nothing to do } +void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { + // nothing to do +} void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { TL.setCaretLoc(ReadSourceLocation(Record, Idx)); } @@ -5016,7 +5606,7 @@ void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { if (Record[Idx++]) TL.setSizeExpr(Reader.ReadExpr(F)); else - TL.setSizeExpr(0); + TL.setSizeExpr(nullptr); } void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { VisitArrayTypeLoc(TL); @@ -5046,8 +5636,8 @@ void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { TL.setLParenLoc(ReadSourceLocation(Record, Idx)); TL.setRParenLoc(ReadSourceLocation(Record, Idx)); TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx)); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { - TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); + for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) { + TL.setParam(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); } } void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { @@ -5103,7 +5693,7 @@ void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { if (Record[Idx++]) TL.setAttrExprOperand(Reader.ReadExpr(F)); else - TL.setAttrExprOperand(0); + TL.setAttrExprOperand(nullptr); } else if (TL.hasAttrEnumOperand()) TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx)); } @@ -5187,7 +5777,7 @@ TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F, unsigned &Idx) { QualType InfoTy = readType(F, Record, Idx); if (InfoTy.isNull()) - return 0; + return nullptr; TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); TypeLocReader TLR(*this, F, Record, Idx); @@ -5374,11 +5964,54 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } -uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, - unsigned &Idx){ - if (Idx >= Record.size()) +void ASTReader::CompleteRedeclChain(const Decl *D) { + if (NumCurrentElementsDeserializing) { + // We arrange to not care about the complete redeclaration chain while we're + // deserializing. Just remember that the AST has marked this one as complete + // but that it's not actually complete yet, so we know we still need to + // complete it later. + PendingIncompleteDeclChains.push_back(const_cast<Decl*>(D)); + return; + } + + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + + // Recursively ensure that the decl context itself is complete + // (in particular, this matters if the decl context is a namespace). + // + // FIXME: This should be performed by lookup instead of here. + cast<Decl>(DC)->getMostRecentDecl(); + + // If this is a named declaration, complete it by looking it up + // within its context. + // + // FIXME: We don't currently handle the cases where we can't do this; + // merging a class definition that contains unnamed entities should merge + // those entities. Likewise, merging a function definition should merge + // all mergeable entities within it. + if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) || + isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) { + if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) { + auto *II = Name.getAsIdentifierInfo(); + if (isa<TranslationUnitDecl>(DC) && II) { + // Outside of C++, we don't have a lookup table for the TU, so update + // the identifier instead. In C++, either way should work fine. + if (II->isOutOfDate()) + updateOutOfDateIdentifier(*II); + } else + DC->lookup(Name); + } + } +} + +uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, + const RecordData &Record, + unsigned &Idx) { + if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXBaseSpecifiers) { + Error("malformed AST file: missing C++ base specifier"); return 0; - + } + unsigned LocalID = Record[Idx++]; return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]); } @@ -5393,8 +6026,8 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { unsigned Code = Cursor.ReadCode(); unsigned RecCode = Cursor.readRecord(Code, Record); if (RecCode != DECL_CXX_BASE_SPECIFIERS) { - Error("Malformed AST file: missing C++ base specifiers"); - return 0; + Error("malformed AST file: missing C++ base specifiers"); + return nullptr; } unsigned Idx = 0; @@ -5427,7 +6060,7 @@ bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { if (!D->isFromASTFile()) - return 0; + return nullptr; GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); return I->second; @@ -5436,14 +6069,14 @@ ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { if (ID < NUM_PREDEF_DECL_IDS) return SourceLocation(); - + unsigned Index = ID - NUM_PREDEF_DECL_IDS; if (Index > DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); return SourceLocation(); } - + if (Decl *D = DeclsLoaded[Index]) return D->getLocation(); @@ -5452,15 +6085,15 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { return ReadSourceLocation(*Rec.F, RawLocation); } -Decl *ASTReader::GetDecl(DeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) { +Decl *ASTReader::GetExistingDecl(DeclID ID) { + if (ID < NUM_PREDEF_DECL_IDS) { switch ((PredefinedDeclIDs)ID) { case PREDEF_DECL_NULL_ID: - return 0; - + return nullptr; + case PREDEF_DECL_TRANSLATION_UNIT_ID: return Context.getTranslationUnitDecl(); - + case PREDEF_DECL_OBJC_ID_ID: return Context.getObjCIdDecl(); @@ -5469,16 +6102,16 @@ Decl *ASTReader::GetDecl(DeclID ID) { case PREDEF_DECL_OBJC_CLASS_ID: return Context.getObjCClassDecl(); - + case PREDEF_DECL_OBJC_PROTOCOL_ID: return Context.getObjCProtocolDecl(); - + case PREDEF_DECL_INT_128_ID: return Context.getInt128Decl(); case PREDEF_DECL_UNSIGNED_INT_128_ID: return Context.getUInt128Decl(); - + case PREDEF_DECL_OBJC_INSTANCETYPE_ID: return Context.getObjCInstanceTypeDecl(); @@ -5486,15 +6119,30 @@ Decl *ASTReader::GetDecl(DeclID ID) { return Context.getBuiltinVaListDecl(); } } - + unsigned Index = ID - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); Error("declaration ID out-of-range for AST file"); - return 0; + return nullptr; } - + + return DeclsLoaded[Index]; +} + +Decl *ASTReader::GetDecl(DeclID ID) { + if (ID < NUM_PREDEF_DECL_IDS) + return GetExistingDecl(ID); + + unsigned Index = ID - NUM_PREDEF_DECL_IDS; + + if (Index >= DeclsLoaded.size()) { + assert(0 && "declaration ID out-of-range for AST file"); + Error("declaration ID out-of-range for AST file"); + return nullptr; + } + if (!DeclsLoaded[Index]) { ReadDeclRecord(ID); if (DeserializationListener) @@ -5779,7 +6427,7 @@ static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC, if (const DeclContext *DefDC = getDefinitiveDeclContext(DC)) return Reader.getOwningModuleFile(cast<Decl>(DefDC)); - return 0; + return nullptr; } bool @@ -5800,14 +6448,19 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, Contexts.push_back(DC); if (DC->isNamespace()) { - MergedDeclsMap::iterator Merged - = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); + auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); if (Merged != MergedDecls.end()) { for (unsigned I = 0, N = Merged->second.size(); I != N; ++I) Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I]))); } } - + if (isa<CXXRecordDecl>(DC)) { + auto Merged = MergedLookups.find(DC); + if (Merged != MergedLookups.end()) + Contexts.insert(Contexts.end(), Merged->second.begin(), + Merged->second.end()); + } + DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); // If we can definitively determine which module file to look into, @@ -5924,15 +6577,23 @@ static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD, ASTConsumer *Consumer) { assert(ImplD && Consumer); - for (ObjCImplDecl::method_iterator - I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I) - Consumer->HandleInterestingDecl(DeclGroupRef(*I)); + for (auto *I : ImplD->methods()) + Consumer->HandleInterestingDecl(DeclGroupRef(I)); Consumer->HandleInterestingDecl(DeclGroupRef(ImplD)); } void ASTReader::PassInterestingDeclsToConsumer() { assert(Consumer); + + if (PassingDeclsToConsumer) + return; + + // Guard variable to avoid recursively redoing the process of passing + // decls to consumer. + SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, + true); + while (!InterestingDecls.empty()) { Decl *D = InterestingDecls.front(); InterestingDecls.pop_front(); @@ -5954,12 +6615,12 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) { if (!Consumer) return; - for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { + for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) { // Force deserialization of this decl, which will cause it to be queued for // passing to the consumer. - GetDecl(ExternalDefinitions[I]); + GetDecl(EagerlyDeserializedDecls[I]); } - ExternalDefinitions.clear(); + EagerlyDeserializedDecls.clear(); PassInterestingDeclsToConsumer(); } @@ -5972,15 +6633,15 @@ void ASTReader::PrintStats() { QualType()); unsigned NumDeclsLoaded = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), - (Decl *)0); + (Decl *)nullptr); unsigned NumIdentifiersLoaded = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), IdentifiersLoaded.end(), - (IdentifierInfo *)0); + (IdentifierInfo *)nullptr); unsigned NumMacrosLoaded = MacrosLoaded.size() - std::count(MacrosLoaded.begin(), MacrosLoaded.end(), - (MacroInfo *)0); + (MacroInfo *)nullptr); unsigned NumSelectorsLoaded = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), SelectorsLoaded.end(), @@ -6164,6 +6825,11 @@ void ASTReader::UpdateSema() { } SemaDeclRefs.clear(); } + + // Update the state of 'pragma clang optimize'. Use the same API as if we had + // encountered the pragma in the source. + if(OptimizeOffPragmaLocation.isValid()) + SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation); } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { @@ -6174,7 +6840,7 @@ IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { // If there is a global index, look there first to determine which modules // provably do not have any results for this identifier. GlobalModuleIndex::HitSet Hits; - GlobalModuleIndex::HitSet *HitsPtr = 0; + GlobalModuleIndex::HitSet *HitsPtr = nullptr; if (!loadGlobalIndex()) { if (GlobalIndex->lookupIdentifier(Name, Hits)) { HitsPtr = &Hits; @@ -6211,7 +6877,7 @@ namespace clang { public: explicit ASTIdentifierIterator(const ASTReader &Reader); - virtual StringRef Next(); + StringRef Next() override; }; } @@ -6330,7 +6996,7 @@ void ASTReader::ReadMethodPool(Selector Sel) { // Get the selector generation and update it to the current generation. unsigned &Generation = SelectorGeneration[Sel]; unsigned PriorGeneration = Generation; - Generation = CurrentGeneration; + Generation = getGeneration(); // Search for methods defined with this selector. ++NumMethodPoolLookups; @@ -6587,11 +7253,11 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { if (ID == 0) - return 0; + return nullptr; if (IdentifiersLoaded.empty()) { Error("no identifier table in AST file"); - return 0; + return nullptr; } ID -= 1; @@ -6637,11 +7303,11 @@ IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { MacroInfo *ASTReader::getMacro(MacroID ID) { if (ID == 0) - return 0; + return nullptr; if (MacrosLoaded.empty()) { Error("no macro table in AST file"); - return 0; + return nullptr; } ID -= NUM_PREDEF_MACRO_IDS; @@ -6688,12 +7354,12 @@ ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) { assert(GlobalID == 0 && "Unhandled global submodule ID"); - return 0; + return nullptr; } if (GlobalID > SubmodulesLoaded.size()) { Error("submodule ID out of range in AST file"); - return 0; + return nullptr; } return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; @@ -6716,7 +7382,7 @@ Selector ASTReader::DecodeSelector(serialization::SelectorID ID) { return Selector(); } - if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) { + if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == nullptr) { // Load this selector from the selector table. GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID); assert(I != GlobalSelectorMap.end() && "Corrupted global selector map"); @@ -7012,16 +7678,16 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, std::pair<CXXCtorInitializer **, unsigned> ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx) { - CXXCtorInitializer **CtorInitializers = 0; + CXXCtorInitializer **CtorInitializers = nullptr; unsigned NumInitializers = Record[Idx++]; if (NumInitializers) { CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *TInfo = 0; + TypeSourceInfo *TInfo = nullptr; bool IsBaseVirtual = false; - FieldDecl *Member = 0; - IndirectFieldDecl *IndirectMember = 0; + FieldDecl *Member = nullptr; + IndirectFieldDecl *IndirectMember = nullptr; CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; switch (Type) { @@ -7101,7 +7767,7 @@ NestedNameSpecifier * ASTReader::ReadNestedNameSpecifier(ModuleFile &F, const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; - NestedNameSpecifier *NNS = 0, *Prev = 0; + NestedNameSpecifier *NNS = nullptr, *Prev = nullptr; for (unsigned I = 0; I != N; ++I) { NestedNameSpecifier::SpecifierKind Kind = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; @@ -7128,8 +7794,8 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F, case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *T = readType(F, Record, Idx).getTypePtrOrNull(); if (!T) - return 0; - + return nullptr; + bool Template = Record[Idx++]; NNS = NestedNameSpecifier::Create(Context, Prev, Template, T); break; @@ -7276,14 +7942,14 @@ IdentifierTable &ASTReader::getIdentifierTable() { /// \brief Record that the given ID maps to the given switch-case /// statement. void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] == 0 && + assert((*CurrSwitchCaseStmts)[ID] == nullptr && "Already have a SwitchCase with this ID"); (*CurrSwitchCaseStmts)[ID] = SC; } /// \brief Retrieve the switch-case statement with the given ID. SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID"); + assert((*CurrSwitchCaseStmts)[ID] != nullptr && "No SwitchCase with this ID"); return (*CurrSwitchCaseStmts)[ID]; } @@ -7298,6 +7964,7 @@ void ASTReader::ReadComments() { I = CommentsCursors.begin(), E = CommentsCursors.end(); I != E; ++I) { + Comments.clear(); BitstreamCursor &Cursor = I->first; serialization::ModuleFile &F = *I->second; SavedStreamPosition SavedPosition(Cursor); @@ -7306,7 +7973,7 @@ void ASTReader::ReadComments() { while (true) { llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); - + switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: @@ -7336,15 +8003,29 @@ void ASTReader::ReadComments() { } } } - NextCursor:; + NextCursor: + Context.Comments.addDeserializedComments(Comments); } - Context.Comments.addCommentsToFront(Comments); +} + +std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { + // If we know the owning module, use it. + if (Module *M = D->getOwningModule()) + return M->getFullModuleName(); + + // Otherwise, use the name of the top-level module the decl is within. + if (ModuleFile *M = getOwningModuleFile(D)) + return M->ModuleName; + + // Not from a module. + return ""; } void ASTReader::finishPendingActions() { - while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() || + while (!PendingIdentifierInfos.empty() || + !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingOdrMergeChecks.empty()) { + !PendingUpdateRecords.empty() || !PendingOdrMergeChecks.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > @@ -7352,14 +8033,21 @@ void ASTReader::finishPendingActions() { TopLevelDeclsMap TopLevelDecls; while (!PendingIdentifierInfos.empty()) { - // FIXME: std::move IdentifierInfo *II = PendingIdentifierInfos.back().first; - SmallVector<uint32_t, 4> DeclIDs = PendingIdentifierInfos.back().second; + SmallVector<uint32_t, 4> DeclIDs = + std::move(PendingIdentifierInfos.back().second); PendingIdentifierInfos.pop_back(); SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]); } - + + // For each decl chain that we wanted to complete while deserializing, mark + // it as "still needs to be completed". + for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { + markIncompleteDeclChain(PendingIncompleteDeclChains[I]); + } + PendingIncompleteDeclChains.clear(); + // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) { loadPendingDeclChain(PendingDeclChains[I]); @@ -7382,14 +8070,14 @@ void ASTReader::finishPendingActions() { SmallVector<PendingMacroInfo, 2> GlobalIDs; GlobalIDs.swap(PendingMacroIDs.begin()[I].second); // Initialize the macro history from chained-PCHs ahead of module imports. - for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; + for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; if (Info.M->Kind != MK_Module) resolvePendingMacro(II, Info); } // Handle module imports. - for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; + for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; if (Info.M->Kind == MK_Module) @@ -7408,6 +8096,30 @@ void ASTReader::finishPendingActions() { Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext()); } + // Perform any pending declaration updates. + // + // Don't do this if we have known-incomplete redecl chains: it relies on + // being able to walk redeclaration chains. + while (PendingDeclChains.empty() && !PendingUpdateRecords.empty()) { + auto Update = PendingUpdateRecords.pop_back_val(); + ReadingKindTracker ReadingKind(Read_Decl, *this); + loadDeclUpdateRecords(Update.first, Update.second); + } + + // Trigger the import of the full definition of each class that had any + // odr-merging problems, so we can produce better diagnostics for them. + for (auto &Merge : PendingOdrMergeFailures) { + Merge.first->buildLookup(); + Merge.first->decls_begin(); + Merge.first->bases_begin(); + Merge.first->vbases_begin(); + for (auto *RD : Merge.second) { + RD->decls_begin(); + RD->bases_begin(); + RD->vbases_begin(); + } + } + // For each declaration from a merged context, check that the canonical // definition of that context also contains a declaration of the same // entity. @@ -7430,16 +8142,14 @@ void ASTReader::finishPendingActions() { llvm::SmallVector<const NamedDecl*, 4> Candidates; for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); !Found && I != E; ++I) { - for (Decl::redecl_iterator RI = (*I)->redecls_begin(), - RE = (*I)->redecls_end(); - RI != RE; ++RI) { - if ((*RI)->getLexicalDeclContext() == CanonDef) { + for (auto RI : (*I)->redecls()) { + if (RI->getLexicalDeclContext() == CanonDef) { // This declaration is present in the canonical definition. If it's // in the same redecl chain, it's the one we're looking for. - if ((*RI)->getCanonicalDecl() == DCanon) + if (RI->getCanonicalDecl() == DCanon) Found = true; else - Candidates.push_back(cast<NamedDecl>(*RI)); + Candidates.push_back(cast<NamedDecl>(RI)); break; } } @@ -7448,11 +8158,11 @@ void ASTReader::finishPendingActions() { if (!Found) { D->setInvalidDecl(); - Module *CanonDefModule = cast<Decl>(CanonDef)->getOwningModule(); + std::string CanonDefModule = + getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) - << D << D->getOwningModule()->getFullModuleName() - << CanonDef << !CanonDefModule - << (CanonDefModule ? CanonDefModule->getFullModuleName() : ""); + << D << getOwningModuleNameForDiagnostic(D) + << CanonDef << CanonDefModule.empty() << CanonDefModule; if (Candidates.empty()) Diag(cast<Decl>(CanonDef)->getLocation(), @@ -7463,6 +8173,8 @@ void ASTReader::finishPendingActions() { diag::note_module_odr_violation_possible_decl) << Candidates[I]; } + + DiagnosedOdrMergeFailures.insert(CanonDef); } } } @@ -7475,49 +8187,39 @@ void ASTReader::finishPendingActions() { DEnd = PendingDefinitions.end(); D != DEnd; ++D) { if (TagDecl *TD = dyn_cast<TagDecl>(*D)) { - if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) { + if (const TagType *TagT = dyn_cast<TagType>(TD->getTypeForDecl())) { // Make sure that the TagType points at the definition. const_cast<TagType*>(TagT)->decl = TD; } - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) { - for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(), - REnd = RD->redecls_end(); - R != REnd; ++R) - cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData; - + if (auto RD = dyn_cast<CXXRecordDecl>(*D)) { + for (auto R : RD->redecls()) + cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData; } continue; } - if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) { + if (auto ID = dyn_cast<ObjCInterfaceDecl>(*D)) { // Make sure that the ObjCInterfaceType points at the definition. const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl)) ->Decl = ID; - for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), - REnd = ID->redecls_end(); - R != REnd; ++R) + for (auto R : ID->redecls()) R->Data = ID->Data; continue; } - if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) { - for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(), - REnd = PD->redecls_end(); - R != REnd; ++R) + if (auto PD = dyn_cast<ObjCProtocolDecl>(*D)) { + for (auto R : PD->redecls()) R->Data = PD->Data; continue; } - RedeclarableTemplateDecl *RTD - = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); - for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(), - REnd = RTD->redecls_end(); - R != REnd; ++R) + auto RTD = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); + for (auto R : RTD->redecls()) R->Common = RTD->Common; } PendingDefinitions.clear(); @@ -7541,6 +8243,46 @@ void ASTReader::finishPendingActions() { MD->setLazyBody(PB->second); } PendingBodies.clear(); + + // Issue any pending ODR-failure diagnostics. + for (auto &Merge : PendingOdrMergeFailures) { + if (!DiagnosedOdrMergeFailures.insert(Merge.first)) + continue; + + bool Diagnosed = false; + for (auto *RD : Merge.second) { + // Multiple different declarations got merged together; tell the user + // where they came from. + if (Merge.first != RD) { + // FIXME: Walk the definition, figure out what's different, + // and diagnose that. + if (!Diagnosed) { + std::string Module = getOwningModuleNameForDiagnostic(Merge.first); + Diag(Merge.first->getLocation(), + diag::err_module_odr_violation_different_definitions) + << Merge.first << Module.empty() << Module; + Diagnosed = true; + } + + Diag(RD->getLocation(), + diag::note_module_odr_violation_different_definitions) + << getOwningModuleNameForDiagnostic(RD); + } + } + + if (!Diagnosed) { + // All definitions are updates to the same declaration. This happens if a + // module instantiates the declaration of a class template specialization + // and two or more other modules instantiate its definition. + // + // FIXME: Indicate which modules had instantiations of this definition. + // FIXME: How can this even happen? + Diag(Merge.first->getLocation(), + diag::err_module_odr_violation_different_instantiations) + << Merge.first; + } + } + PendingOdrMergeFailures.clear(); } void ASTReader::FinishedDeserializing() { @@ -7553,20 +8295,10 @@ void ASTReader::FinishedDeserializing() { } --NumCurrentElementsDeserializing; - if (NumCurrentElementsDeserializing == 0 && - Consumer && !PassingDeclsToConsumer) { - // Guard variable to avoid recursively redoing the process of passing - // decls to consumer. - SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); - - while (!InterestingDecls.empty()) { - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - Decl *D = InterestingDecls.front(); - InterestingDecls.pop_front(); - PassInterestingDeclToConsumer(D); - } + if (NumCurrentElementsDeserializing == 0 && Consumer) { + // We are not in recursive loading, so it's safe to pass the "interesting" + // decls to the consumer. + PassInterestingDeclsToConsumer(); } } @@ -7585,34 +8317,39 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { } } -ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, bool DisableValidation, - bool AllowASTWithCompilerErrors, bool UseGlobalIndex) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), - Consumer(0), ModuleMgr(PP.getFileManager()), - isysroot(isysroot), DisableValidation(DisableValidation), - AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), - UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false), - CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts), - NumSLocEntriesRead(0), TotalNumSLocEntries(0), - NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), - TotalNumMacros(0), NumIdentifierLookups(0), NumIdentifierLookupHits(0), - NumSelectorsRead(0), NumMethodPoolEntriesRead(0), - NumMethodPoolLookups(0), NumMethodPoolHits(0), - NumMethodPoolTableLookups(0), NumMethodPoolTableHits(0), - TotalNumMethodPoolEntries(0), - NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), - NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), - TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), - PassingDeclsToConsumer(false), - NumCXXBaseSpecifiersLoaded(0), ReadingKind(Read_None) -{ +ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, + bool DisableValidation, bool AllowASTWithCompilerErrors, + bool AllowConfigurationMismatch, bool ValidateSystemInputs, + bool UseGlobalIndex) + : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr), + OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()), + FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), + SemaObj(nullptr), PP(PP), Context(Context), Consumer(nullptr), + ModuleMgr(PP.getFileManager()), isysroot(isysroot), + DisableValidation(DisableValidation), + AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), + AllowConfigurationMismatch(AllowConfigurationMismatch), + ValidateSystemInputs(ValidateSystemInputs), + UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false), + CurrSwitchCaseStmts(&SwitchCaseStmts), + NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0), + TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0), + NumIdentifierLookups(0), NumIdentifierLookupHits(0), NumSelectorsRead(0), + NumMethodPoolEntriesRead(0), NumMethodPoolLookups(0), + NumMethodPoolHits(0), NumMethodPoolTableLookups(0), + NumMethodPoolTableHits(0), TotalNumMethodPoolEntries(0), + NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), + NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), + TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), + PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0), + ReadingKind(Read_None) { SourceMgr.setExternalSLocEntrySource(this); } ASTReader::~ASTReader() { + if (OwnsDeserializationListener) + delete DeserializationListener; + for (DeclContextVisibleUpdatesPending::iterator I = PendingVisibleUpdates.begin(), E = PendingVisibleUpdates.end(); |