diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp | 1341 |
1 files changed, 781 insertions, 560 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index ae41654..416164e 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -80,10 +80,14 @@ 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::ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain, + bool AllowCompatibleDifferences) { + return First->ReadLanguageOptions(LangOpts, Complain, + AllowCompatibleDifferences) || + Second->ReadLanguageOptions(LangOpts, Complain, + AllowCompatibleDifferences); } bool ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts, @@ -155,11 +159,14 @@ ASTReaderListener::~ASTReaderListener() {} /// language options. /// /// \param Diags If non-NULL, diagnostics will be emitted via this engine. +/// \param AllowCompatibleDifferences If true, differences between compatible +/// language options will be permitted. /// /// \returns true if the languagae options mis-match, false otherwise. static bool checkLanguageOptions(const LangOptions &LangOpts, const LangOptions &ExistingLangOpts, - DiagnosticsEngine *Diags) { + DiagnosticsEngine *Diags, + bool AllowCompatibleDifferences = true) { #define LANGOPT(Name, Bits, Default, Description) \ if (ExistingLangOpts.Name != LangOpts.Name) { \ if (Diags) \ @@ -184,6 +191,14 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return true; \ } +#define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \ + if (!AllowCompatibleDifferences) \ + LANGOPT(Name, Bits, Default, Description) + +#define COMPATIBLE_ENUM_LANGOPT(Name, Bits, Default, Description) \ + if (!AllowCompatibleDifferences) \ + ENUM_LANGOPT(Name, Bits, Default, Description) + #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" @@ -278,10 +293,12 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts, bool PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain) { + bool Complain, + bool AllowCompatibleDifferences) { const LangOptions &ExistingLangOpts = PP.getLangOpts(); return checkLanguageOptions(LangOpts, ExistingLangOpts, - Complain? &Reader.Diags : nullptr); + Complain ? &Reader.Diags : nullptr, + AllowCompatibleDifferences); } bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, @@ -389,14 +406,14 @@ bool PCHValidator::ReadDiagnosticOptions( // 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. + // module import of an implicitly-loaded module file. // 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) + if (TopImport->Kind != MK_ImplicitModule) return false; StringRef ModuleName = TopImport->ModuleName; @@ -543,8 +560,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, continue; SuggestedPredefines += "#include \""; - SuggestedPredefines += - HeaderSearch::NormalizeDashIncludePath(File, FileMgr); + SuggestedPredefines += File; SuggestedPredefines += "\"\n"; } @@ -556,8 +572,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, continue; SuggestedPredefines += "#__include_macros \""; - SuggestedPredefines += - HeaderSearch::NormalizeDashIncludePath(File, FileMgr); + SuggestedPredefines += File; SuggestedPredefines += "\"\n##\n"; } @@ -635,14 +650,14 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* 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; - unsigned NumFactoryMethods = NumFactoryMethodsAndBits >> 2; + unsigned FullInstanceBits = endian::readNext<uint16_t, little, unaligned>(d); + unsigned FullFactoryBits = endian::readNext<uint16_t, little, unaligned>(d); + Result.InstanceBits = FullInstanceBits & 0x3; + Result.InstanceHasMoreThanOneDecl = (FullInstanceBits >> 2) & 0x1; + Result.FactoryBits = FullFactoryBits & 0x3; + Result.FactoryHasMoreThanOneDecl = (FullFactoryBits >> 2) & 0x1; + unsigned NumInstanceMethods = FullInstanceBits >> 3; + unsigned NumFactoryMethods = FullFactoryBits >> 3; // Load instance methods for (unsigned I = 0; I != NumInstanceMethods; ++I) { @@ -774,15 +789,16 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, DataLen -= 4; SmallVector<uint32_t, 8> LocalMacroIDs; if (hasSubmoduleMacros) { - while (uint32_t LocalMacroID = - endian::readNext<uint32_t, little, unaligned>(d)) { + while (true) { + uint32_t LocalMacroID = + endian::readNext<uint32_t, little, unaligned>(d); DataLen -= 4; + if (LocalMacroID == 0xdeadbeef) break; LocalMacroIDs.push_back(LocalMacroID); } - DataLen -= 4; } - if (F.Kind == MK_Module) { + if (F.Kind == MK_ImplicitModule || F.Kind == MK_ExplicitModule) { // Macro definitions are stored from newest to oldest, so reverse them // before registering them. llvm::SmallVector<unsigned, 8> MacroSizes; @@ -1013,7 +1029,7 @@ void ASTReader::Error(unsigned DiagID, /// \brief Read the line table in the source manager block. /// \returns true if there was an error. bool ASTReader::ParseLineTable(ModuleFile &F, - SmallVectorImpl<uint64_t> &Record) { + const RecordData &Record) { unsigned Idx = 0; LineTableInfo &LineTable = SourceMgr.getLineTable(); @@ -1021,10 +1037,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F, std::map<int, int> FileIDs; for (int I = 0, N = Record[Idx++]; I != N; ++I) { // Extract the file name - unsigned FilenameLen = Record[Idx++]; - std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen); - Idx += FilenameLen; - MaybeAddSystemRootToFilename(F, Filename); + auto Filename = ReadPath(F, Record, Idx); FileIDs[I] = LineTable.getLineTableFilenameID(Filename); } @@ -1225,9 +1238,9 @@ bool ASTReader::ReadSLocEntry(int ID) { return true; } - llvm::MemoryBuffer *Buffer + std::unique_ptr<llvm::MemoryBuffer> Buffer = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), File->getName()); - SourceMgr.overrideFileContents(File, Buffer); + SourceMgr.overrideFileContents(File, std::move(Buffer)); } break; @@ -1239,7 +1252,8 @@ bool ASTReader::ReadSLocEntry(int ID) { SrcMgr::CharacteristicKind FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); - if (IncludeLoc.isInvalid() && F->Kind == MK_Module) { + if (IncludeLoc.isInvalid() && + (F->Kind == MK_ImplicitModule || F->Kind == MK_ExplicitModule)) { IncludeLoc = getImportLocation(F); } unsigned Code = SLocEntryCursor.ReadCode(); @@ -1252,10 +1266,10 @@ bool ASTReader::ReadSLocEntry(int ID) { return true; } - llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name); - SourceMgr.createFileID(Buffer, FileCharacter, ID, BaseOffset + Offset, - IncludeLoc); + std::unique_ptr<llvm::MemoryBuffer> Buffer = + llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name); + SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID, + BaseOffset + Offset, IncludeLoc); break; } @@ -1285,7 +1299,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { // Find which module file this entry lands in. ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second; - if (M->Kind != MK_Module) + if (M->Kind != MK_ImplicitModule && M->Kind != MK_ExplicitModule) return std::make_pair(SourceLocation(), ""); // FIXME: Can we map this down to a particular submodule? That would be @@ -1466,11 +1480,11 @@ ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) { return llvm::hash_combine(ikey.Size, ikey.ModTime); } - + HeaderFileInfoTrait::internal_key_type HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) { internal_key_type ikey = { FE->getSize(), FE->getModificationTime(), - FE->getName() }; + FE->getName(), /*Imported*/false }; return ikey; } @@ -1478,14 +1492,24 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) { if (a.Size != b.Size || a.ModTime != b.ModTime) return false; - if (strcmp(a.Filename, b.Filename) == 0) + if (llvm::sys::path::is_absolute(a.Filename) && + strcmp(a.Filename, b.Filename) == 0) return true; // Determine whether the actual files are equivalent. FileManager &FileMgr = Reader.getFileManager(); - const FileEntry *FEA = FileMgr.getFile(a.Filename); - const FileEntry *FEB = FileMgr.getFile(b.Filename); - return (FEA && FEA == FEB); + auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* { + if (!Key.Imported) + return FileMgr.getFile(Key.Filename); + + std::string Resolved = Key.Filename; + Reader.ResolveImportedPath(M, Resolved); + return FileMgr.getFile(Resolved); + }; + + const FileEntry *FEA = GetFile(a); + const FileEntry *FEB = GetFile(b); + return FEA && FEA == FEB; } std::pair<unsigned, unsigned> @@ -1503,6 +1527,7 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { 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; + ikey.Imported = true; return ikey; } @@ -1542,7 +1567,14 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, FileManager &FileMgr = Reader.getFileManager(); ModuleMap &ModMap = Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); - ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), HFI.getHeaderRole()); + // FIXME: This information should be propagated through the + // SUBMODULE_HEADER etc records rather than from here. + // FIXME: We don't ever mark excluded headers. + std::string Filename = key.Filename; + if (key.Imported) + Reader.ResolveImportedPath(M, Filename); + Module::Header H = { key.Filename, FileMgr.getFile(Filename) }; + ModMap.addHeader(Mod, H, HFI.getHeaderRole()); } } @@ -1732,10 +1764,12 @@ struct ASTReader::ModuleMacroInfo { return llvm::makeArrayRef(Overrides + 1, *Overrides); } - DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const { + MacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const { if (!MI) - return nullptr; - return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true); + return PP.AllocateUndefMacroDirective(ImportLoc, SubModID, + getOverriddenSubmodules()); + return PP.AllocateDefMacroDirective(MI, ImportLoc, SubModID, + getOverriddenSubmodules()); } }; @@ -1772,7 +1806,8 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo) { assert(II); - if (PMInfo.M->Kind != MK_Module) { + if (PMInfo.M->Kind != MK_ImplicitModule && + PMInfo.M->Kind != MK_ExplicitModule) { installPCHMacroDirectives(II, *PMInfo.M, PMInfo.PCHMacroData.MacroDirectivesOffset); return; @@ -1790,13 +1825,13 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, // install if we make this module visible. HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI)); } else { - installImportedMacro(II, MMI, Owner, /*FromFinalization*/false); + installImportedMacro(II, MMI, Owner); } } void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, ModuleFile &M, uint64_t Offset) { - assert(M.Kind != MK_Module); + assert(M.Kind != MK_ImplicitModule && M.Kind != MK_ExplicitModule); BitstreamCursor &Cursor = M.MacroCursor; SavedStreamPosition SavedPosition(Cursor); @@ -1828,23 +1863,36 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, case MacroDirective::MD_Define: { GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]); MacroInfo *MI = getMacro(GMacID); - bool isImported = Record[Idx++]; - bool isAmbiguous = Record[Idx++]; + SubmoduleID ImportedFrom = Record[Idx++]; + bool IsAmbiguous = Record[Idx++]; + llvm::SmallVector<unsigned, 4> Overrides; + if (ImportedFrom) { + Overrides.insert(Overrides.end(), + &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]); + Idx += Overrides.size() + 1; + } DefMacroDirective *DefMD = - PP.AllocateDefMacroDirective(MI, Loc, isImported); - DefMD->setAmbiguous(isAmbiguous); + PP.AllocateDefMacroDirective(MI, Loc, ImportedFrom, Overrides); + DefMD->setAmbiguous(IsAmbiguous); MD = DefMD; break; } - case MacroDirective::MD_Undefine: - MD = PP.AllocateUndefMacroDirective(Loc); + case MacroDirective::MD_Undefine: { + SubmoduleID ImportedFrom = Record[Idx++]; + llvm::SmallVector<unsigned, 4> Overrides; + if (ImportedFrom) { + Overrides.insert(Overrides.end(), + &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]); + Idx += Overrides.size() + 1; + } + MD = PP.AllocateUndefMacroDirective(Loc, ImportedFrom, Overrides); break; - case MacroDirective::MD_Visibility: { + } + case MacroDirective::MD_Visibility: bool isPublic = Record[Idx++]; MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic); break; } - } if (!Latest) Latest = MD; @@ -1877,19 +1925,27 @@ static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, } void ASTReader::removeOverriddenMacros(IdentifierInfo *II, + SourceLocation ImportLoc, 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. + // It won't be there if we're in the middle of making the owner visible. 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); + auto HiddenIt = HiddenNamesMap.find(Owner); + if (HiddenIt != HiddenNamesMap.end()) { + HiddenNames &Hidden = HiddenIt->second; + HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II); + if (HI != Hidden.HiddenMacros.end()) { + // Register the macro now so we don't lose it when we re-export. + PP.appendMacroDirective(II, HI->second->import(PP, ImportLoc)); + + auto SubOverrides = HI->second->getOverriddenSubmodules(); + Hidden.HiddenMacros.erase(HI); + removeOverriddenMacros(II, ImportLoc, Ambig, SubOverrides); + } } // If this macro is already in our list of conflicts, remove it from there. @@ -1903,6 +1959,7 @@ void ASTReader::removeOverriddenMacros(IdentifierInfo *II, ASTReader::AmbiguousMacros * ASTReader::removeOverriddenMacros(IdentifierInfo *II, + SourceLocation ImportLoc, ArrayRef<SubmoduleID> Overrides) { MacroDirective *Prev = PP.getMacroDirective(II); if (!Prev && Overrides.empty()) @@ -1915,7 +1972,7 @@ ASTReader::removeOverriddenMacros(IdentifierInfo *II, AmbiguousMacros &Ambig = AmbiguousMacroDefs[II]; Ambig.push_back(PrevDef); - removeOverriddenMacros(II, Ambig, Overrides); + removeOverriddenMacros(II, ImportLoc, Ambig, Overrides); if (!Ambig.empty()) return &Ambig; @@ -1927,7 +1984,7 @@ ASTReader::removeOverriddenMacros(IdentifierInfo *II, if (PrevDef) Ambig.push_back(PrevDef); - removeOverriddenMacros(II, Ambig, Overrides); + removeOverriddenMacros(II, ImportLoc, Ambig, Overrides); if (!Ambig.empty()) { AmbiguousMacros &Result = AmbiguousMacroDefs[II]; @@ -1941,11 +1998,11 @@ ASTReader::removeOverriddenMacros(IdentifierInfo *II, } void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, - Module *Owner, bool FromFinalization) { + Module *Owner) { assert(II && Owner); SourceLocation ImportLoc = Owner->MacroVisibilityLoc; - if (ImportLoc.isInvalid() && !FromFinalization) { + if (ImportLoc.isInvalid()) { // 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 @@ -1955,18 +2012,16 @@ void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, } AmbiguousMacros *Prev = - removeOverriddenMacros(II, MMI->getOverriddenSubmodules()); + removeOverriddenMacros(II, ImportLoc, 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); + MacroDirective *Imported = MMI->import(PP, ImportLoc); + DefMacroDirective *MD = dyn_cast<DefMacroDirective>(Imported); // If there's no ambiguity, just install the macro. if (!Prev) { - if (MD) - PP.appendMacroDirective(II, MD); - else - PP.appendMacroDirective(II, PP.AllocateUndefMacroDirective(ImportLoc)); + PP.appendMacroDirective(II, Imported); return; } assert(!Prev->empty()); @@ -1974,10 +2029,14 @@ void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, 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. + // imported directive, as if by a local #pragma pop_macro. MacroInfo *NewMI = Prev->back()->getInfo(); Prev->pop_back(); - MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc, /*Imported*/true); + MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc); + + // Install our #undef first so that we don't lose track of it. We'll replace + // this with whichever macro definition ends up winning. + PP.appendMacroDirective(II, Imported); } // We're introducing a macro definition that creates or adds to an ambiguity. @@ -2035,14 +2094,14 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { 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); - + ResolveImportedPath(F, Filename); + InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden }; return R; } @@ -2128,12 +2187,23 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { bool IsOutOfDate = false; // For an overridden file, there is nothing to validate. - if (!Overridden && (StoredSize != File->getSize() -#if !defined(LLVM_ON_WIN32) + if (!Overridden && // + (StoredSize != File->getSize() || +#if defined(LLVM_ON_WIN32) + false +#else // 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() + // + // This also happens in networked file systems, so disable this + // check if validation is disabled or if we have an explicitly + // built PCM file. + // + // FIXME: Should we also do this for PCH files? They could also + // reasonably get shared across a network during a distributed build. + (StoredTime != File->getModificationTime() && !DisableValidation && + F.Kind != MK_ExplicitModule) #endif )) { if (Complain) { @@ -2169,46 +2239,22 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { return IF; } -const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { - ModuleFile &M = ModuleMgr.getPrimaryModule(); - std::string Filename = filenameStrRef; - MaybeAddSystemRootToFilename(M, Filename); - const FileEntry *File = FileMgr.getFile(Filename); - if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() && - M.OriginalDir != CurrentDir) { - std::string resolved = resolveFileRelativeToOriginalDir(Filename, - M.OriginalDir, - CurrentDir); - if (!resolved.empty()) - File = FileMgr.getFile(resolved); - } - - return File; +/// \brief If we are loading a relocatable PCH or module file, and the filename +/// is not an absolute path, add the system or module root to the beginning of +/// the file name. +void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) { + // Resolve relative to the base directory, if we have one. + if (!M.BaseDirectory.empty()) + return ResolveImportedPath(Filename, M.BaseDirectory); } -/// \brief If we are loading a relocatable PCH file, and the filename is -/// not an absolute path, add the system root to the beginning of the file -/// name. -void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, - std::string &Filename) { - // If this is not a relocatable PCH file, there's nothing to do. - if (!M.RelocatablePCH) - return; - +void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) { if (Filename.empty() || llvm::sys::path::is_absolute(Filename)) return; - if (isysroot.empty()) { - // If no system root was given, default to '/' - Filename.insert(Filename.begin(), '/'); - return; - } - - unsigned Length = isysroot.size(); - if (isysroot[Length - 1] != '/') - Filename.insert(Filename.begin(), '/'); - - Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end()); + SmallString<128> Buffer; + llvm::sys::path::append(Buffer, Prefix, Filename); + Filename.assign(Buffer.begin(), Buffer.end()); } ASTReader::ASTReadResult @@ -2223,8 +2269,16 @@ ASTReader::ReadControlBlock(ModuleFile &F, return Failure; } + // Should we allow the configuration of the module file to differ from the + // configuration of the current translation unit in a compatible way? + // + // FIXME: Allow this for files explicitly specified with -include-pch too. + bool AllowCompatibleConfigurationMismatch = F.Kind == MK_ExplicitModule; + // Read all of the records and blocks in the control block. RecordData Record; + unsigned NumInputs = 0; + unsigned NumUserInputs = 0; while (1) { llvm::BitstreamEntry Entry = Stream.advance(); @@ -2237,15 +2291,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, 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)) { + // All user input files reside at the index range [0, NumUserInputs), and + // system input files reside at [NumUserInputs, NumInputs). + if (!DisableValidation) { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; // If we are reading a module, we will create a verification timestamp, @@ -2254,7 +2302,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, unsigned N = NumUserInputs; if (ValidateSystemInputs || - (HSOpts.ModulesValidateOncePerBuildSession && F.Kind == MK_Module)) + (HSOpts.ModulesValidateOncePerBuildSession && + F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp && + F.Kind == MK_ImplicitModule)) N = NumInputs; for (unsigned I = 0; I < N; ++I) { @@ -2324,6 +2374,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, } F.RelocatablePCH = Record[4]; + // Relative paths in a relocatable PCH are relative to our sysroot. + if (F.RelocatablePCH) + F.BaseDirectory = isysroot.empty() ? "/" : isysroot; const std::string &CurBranch = getClangFullRepositoryVersion(); StringRef ASTBranch = Blob; @@ -2335,6 +2388,11 @@ ASTReader::ReadControlBlock(ModuleFile &F, break; } + case SIGNATURE: + assert((!F.Signature || F.Signature == Record[0]) && "signature changed"); + F.Signature = Record[0]; + break; + case IMPORTS: { // Load each of the imported PCH files. unsigned Idx = 0, N = Record.size(); @@ -2348,14 +2406,12 @@ ASTReader::ReadControlBlock(ModuleFile &F, SourceLocation::getFromRawEncoding(Record[Idx++]); off_t StoredSize = (off_t)Record[Idx++]; time_t StoredModTime = (time_t)Record[Idx++]; - unsigned Length = Record[Idx++]; - SmallString<128> ImportedFile(Record.begin() + Idx, - Record.begin() + Idx + Length); - Idx += Length; + ASTFileSignature StoredSignature = Record[Idx++]; + auto ImportedFile = ReadPath(F, Record, Idx); // Load the AST file. switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded, - StoredSize, StoredModTime, + StoredSize, StoredModTime, StoredSignature, ClientLoadCapabilities)) { case Failure: return Failure; // If we have to ignore the dependency, we'll have to ignore this too. @@ -2372,8 +2428,10 @@ ASTReader::ReadControlBlock(ModuleFile &F, case LANGUAGE_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; + // FIXME: The &F == *ModuleMgr.begin() check is wrong for modules. if (Listener && &F == *ModuleMgr.begin() && - ParseLanguageOptions(Record, Complain, *Listener) && + ParseLanguageOptions(Record, Complain, *Listener, + AllowCompatibleConfigurationMismatch) && !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; @@ -2391,6 +2449,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, case DIAGNOSTIC_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0; if (Listener && &F == *ModuleMgr.begin() && + !AllowCompatibleConfigurationMismatch && ParseDiagnosticOptions(Record, Complain, *Listener) && !DisableValidation) return OutOfDate; @@ -2400,6 +2459,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, case FILE_SYSTEM_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && + !AllowCompatibleConfigurationMismatch && ParseFileSystemOptions(Record, Complain, *Listener) && !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; @@ -2409,6 +2469,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, case HEADER_SEARCH_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && + !AllowCompatibleConfigurationMismatch && ParseHeaderSearchOptions(Record, Complain, *Listener) && !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; @@ -2418,6 +2479,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, case PREPROCESSOR_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && + !AllowCompatibleConfigurationMismatch && ParsePreprocessorOptions(Record, Complain, *Listener, SuggestedPredefines) && !DisableValidation && !AllowConfigurationMismatch) @@ -2429,7 +2491,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.OriginalSourceFileID = FileID::get(Record[0]); F.ActualOriginalSourceFileName = Blob; F.OriginalSourceFileName = F.ActualOriginalSourceFileName; - MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName); + ResolveImportedPath(F, F.OriginalSourceFileName); break; case ORIGINAL_FILE_ID: @@ -2446,46 +2508,43 @@ ASTReader::ReadControlBlock(ModuleFile &F, 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. + case MODULE_DIRECTORY: { 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; + "MODULE_DIRECTORY found before MODULE_NAME"); + // If we've already loaded a module map file covering this module, we may + // have a better path for it (relative to the current build). + Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + if (M && M->Directory) { + // If we're implicitly loading a module, the base directory can't + // change between the build and use. + if (F.Kind != MK_ExplicitModule) { + const DirectoryEntry *BuildDir = + PP.getFileManager().getDirectory(Blob); + if (!BuildDir || BuildDir != M->Directory) { + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_imported_module_relocated) + << F.ModuleName << Blob << M->Directory->getName(); + return OutOfDate; + } } + F.BaseDirectory = M->Directory->getName(); + } else { + F.BaseDirectory = Blob; } + break; + } - if (Listener) - Listener->ReadModuleMapFile(F.ModuleMapPath); + case MODULE_MAP_FILE: + if (ASTReadResult Result = + ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities)) + return Result; break; case INPUT_FILE_OFFSETS: + NumInputs = Record[0]; + NumUserInputs = Record[1]; F.InputFileOffsets = (const uint32_t *)Blob.data(); - F.InputFilesLoaded.resize(Record[0]); + F.InputFilesLoaded.resize(NumInputs); break; } } @@ -2628,7 +2687,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { F.TypeRemap.insertOrReplace( std::make_pair(LocalBaseTypeIndex, F.BaseTypeIndex - LocalBaseTypeIndex)); - + TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes); } break; @@ -2658,7 +2717,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Introduce the global -> local mapping for declarations within this // module. F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID; - + DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); } break; @@ -2687,7 +2746,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { 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 @@ -2729,8 +2787,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { F.IdentifierRemap.insertOrReplace( std::make_pair(LocalBaseIdentifierID, F.BaseIdentifierID - LocalBaseIdentifierID)); - - IdentifiersLoaded.resize(IdentifiersLoaded.size() + + IdentifiersLoaded.resize(IdentifiersLoaded.size() + F.LocalNumIdentifiers); } break; @@ -2823,7 +2881,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { std::make_pair(LocalBaseSelectorID, F.BaseSelectorID - LocalBaseSelectorID)); - SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors); + SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors); } break; } @@ -2904,19 +2962,16 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } // 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 - IdentifierRemap(F.IdentifierRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder - MacroRemap(F.MacroRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder - PreprocessedEntityRemap(F.PreprocessedEntityRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder - SubmoduleRemap(F.SubmoduleRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder - SelectorRemap(F.SelectorRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap); - ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap); + typedef ContinuousRangeMap<uint32_t, int, 2>::Builder + RemapBuilder; + RemapBuilder SLocRemap(F.SLocRemap); + RemapBuilder IdentifierRemap(F.IdentifierRemap); + RemapBuilder MacroRemap(F.MacroRemap); + RemapBuilder PreprocessedEntityRemap(F.PreprocessedEntityRemap); + RemapBuilder SubmoduleRemap(F.SubmoduleRemap); + RemapBuilder SelectorRemap(F.SelectorRemap); + RemapBuilder DeclRemap(F.DeclRemap); + RemapBuilder TypeRemap(F.TypeRemap); while(Data < DataEnd) { using namespace llvm::support; @@ -2946,26 +3001,23 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { 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))); - IdentifierRemap.insert( - std::make_pair(IdentifierIDOffset, - OM->BaseIdentifierID - IdentifierIDOffset)); - MacroRemap.insert(std::make_pair(MacroIDOffset, - OM->BaseMacroID - MacroIDOffset)); - PreprocessedEntityRemap.insert( - std::make_pair(PreprocessedEntityIDOffset, - OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset)); - SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset, - OM->BaseSubmoduleID - SubmoduleIDOffset)); - SelectorRemap.insert(std::make_pair(SelectorIDOffset, - OM->BaseSelectorID - SelectorIDOffset)); - DeclRemap.insert(std::make_pair(DeclIDOffset, - OM->BaseDeclID - DeclIDOffset)); - - TypeRemap.insert(std::make_pair(TypeIndexOffset, - OM->BaseTypeIndex - TypeIndexOffset)); + uint32_t None = std::numeric_limits<uint32_t>::max(); + + auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset, + RemapBuilder &Remap) { + if (Offset != None) + Remap.insert(std::make_pair(Offset, + static_cast<int>(BaseOffset - Offset))); + }; + mapOffset(SLocOffset, OM->SLocEntryBaseOffset, SLocRemap); + mapOffset(IdentifierIDOffset, OM->BaseIdentifierID, IdentifierRemap); + mapOffset(MacroIDOffset, OM->BaseMacroID, MacroRemap); + mapOffset(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID, + PreprocessedEntityRemap); + mapOffset(SubmoduleIDOffset, OM->BaseSubmoduleID, SubmoduleRemap); + mapOffset(SelectorIDOffset, OM->BaseSelectorID, SelectorRemap); + mapOffset(DeclIDOffset, OM->BaseDeclID, DeclRemap); + mapOffset(TypeIndexOffset, OM->BaseTypeIndex, TypeRemap); // Global -> local mappings. F.GlobalToLocalDeclIDs[OM] = DeclIDOffset; @@ -3206,7 +3258,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; case IMPORTED_MODULES: { - if (F.Kind != MK_Module) { + if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) { // 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. @@ -3287,10 +3339,110 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]); break; + + case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES: + for (unsigned I = 0, N = Record.size(); I != N; ++I) + UnusedLocalTypedefNameCandidates.push_back( + getGlobalDeclID(F, Record[I])); + break; } } } +ASTReader::ASTReadResult +ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, + const ModuleFile *ImportedBy, + unsigned ClientLoadCapabilities) { + unsigned Idx = 0; + F.ModuleMapPath = ReadPath(F, Record, Idx); + + if (F.Kind == MK_ExplicitModule) { + // For an explicitly-loaded module, we don't care whether the original + // module map file exists or matches. + return Success; + } + + // 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 MODULE_MAP_FILE"); + if (F.Kind == MK_ImplicitModule && + (*ModuleMgr.begin())->Kind != MK_MainFile) { + // An implicitly-loaded module file should have its module listed in some + // module map file that we've already loaded. + Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + auto &Map = PP.getHeaderSearchInfo().getModuleMap(); + const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr; + if (!ModMap) { + assert(ImportedBy && "top-level import should be verified"); + if ((ClientLoadCapabilities & ARR_Missing) == 0) + Diag(diag::err_imported_module_not_found) << F.ModuleName << F.FileName + << ImportedBy->FileName + << F.ModuleMapPath; + return Missing; + } + + assert(M->Name == F.ModuleName && "found module with different name"); + + // Check the primary module map file. + const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath); + if (StoredModMap == nullptr || StoredModMap != ModMap) { + assert(ModMap && "found module is missing module map file"); + assert(ImportedBy && "top-level import should be verified"); + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_imported_module_modmap_changed) + << F.ModuleName << ImportedBy->FileName + << ModMap->getName() << F.ModuleMapPath; + return OutOfDate; + } + + llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps; + for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) { + // FIXME: we should use input files rather than storing names. + std::string Filename = ReadPath(F, Record, Idx); + const FileEntry *F = + FileMgr.getFile(Filename, false, false); + if (F == nullptr) { + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Error("could not find file '" + Filename +"' referenced by AST file"); + return OutOfDate; + } + AdditionalStoredMaps.insert(F); + } + + // Check any additional module map files (e.g. module.private.modulemap) + // that are not in the pcm. + if (auto *AdditionalModuleMaps = Map.getAdditionalModuleMapFiles(M)) { + for (const FileEntry *ModMap : *AdditionalModuleMaps) { + // Remove files that match + // Note: SmallPtrSet::erase is really remove + if (!AdditionalStoredMaps.erase(ModMap)) { + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_module_different_modmap) + << F.ModuleName << /*new*/0 << ModMap->getName(); + return OutOfDate; + } + } + } + + // Check any additional module map files that are in the pcm, but not + // found in header search. Cases that match are already removed. + for (const FileEntry *ModMap : AdditionalStoredMaps) { + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_module_different_modmap) + << F.ModuleName << /*not new*/1 << ModMap->getName(); + return OutOfDate; + } + } + + if (Listener) + Listener->ReadModuleMapFile(F.ModuleMapPath); + return Success; +} + + /// \brief Move the given method to the back of the global list of methods. static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { // Find the entry for this selector in the method pool. @@ -3305,7 +3457,7 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { bool Found = false; for (ObjCMethodList *List = &Start; List; List = List->getNext()) { if (!Found) { - if (List->Method == Method) { + if (List->getMethod() == Method) { Found = true; } else { // Keep searching. @@ -3314,9 +3466,9 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { } if (List->getNext()) - List->Method = List->getNext()->Method; + List->setMethod(List->getNext()->getMethod()); else - List->Method = Method; + List->setMethod(Method); } } @@ -3336,8 +3488,13 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner, assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) && "nothing to make visible?"); - for (const auto &Macro : Names.HiddenMacros) - installImportedMacro(Macro.first, Macro.second, Owner, FromFinalization); + for (const auto &Macro : Names.HiddenMacros) { + if (FromFinalization) + PP.appendMacroDirective(Macro.first, + Macro.second->import(PP, SourceLocation())); + else + installImportedMacro(Macro.first, Macro.second, Owner); + } } void ASTReader::makeModuleVisible(Module *Mod, @@ -3385,7 +3542,7 @@ void ASTReader::makeModuleVisible(Module *Mod, for (SmallVectorImpl<Module *>::iterator I = Exports.begin(), E = Exports.end(); I != E; ++I) { Module *Exported = *I; - if (Visited.insert(Exported)) + if (Visited.insert(Exported).second) Stack.push_back(Exported); } @@ -3435,10 +3592,9 @@ bool ASTReader::isGlobalIndexUnavailable() const { 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()) + std::error_code EC; + llvm::raw_fd_ostream OS(TimestampFilename, EC, llvm::sys::fs::F_Text); + if (EC) return; OS << "Timestamp file\n"; } @@ -3460,7 +3616,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, SmallVector<ImportedModule, 4> Loaded; switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc, /*ImportedBy=*/nullptr, Loaded, - 0, 0, + 0, 0, 0, ClientLoadCapabilities)) { case Failure: case Missing: @@ -3618,7 +3774,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, // in the filesystem). for (unsigned I = 0, N = Loaded.size(); I != N; ++I) { ImportedModule &M = Loaded[I]; - if (M.Mod->Kind == MK_Module) { + if (M.Mod->Kind == MK_ImplicitModule) { updateModuleTimestamp(*M.Mod); } } @@ -3627,6 +3783,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, return Success; } +static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile); + ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, @@ -3634,12 +3792,14 @@ ASTReader::ReadASTCore(StringRef FileName, ModuleFile *ImportedBy, SmallVectorImpl<ImportedModule> &Loaded, off_t ExpectedSize, time_t ExpectedModTime, + ASTFileSignature ExpectedSignature, unsigned ClientLoadCapabilities) { ModuleFile *M; std::string ErrorStr; ModuleManager::AddModuleResult AddResult = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, getGeneration(), ExpectedSize, ExpectedModTime, + ExpectedSignature, readASTFileSignature, M, ErrorStr); switch (AddResult) { @@ -3651,7 +3811,7 @@ ASTReader::ReadASTCore(StringRef FileName, break; case ModuleManager::Missing: - // The module file was missing; if the client handle handle, that, return + // The module file was missing; if the client can handle that, return // it. if (ClientLoadCapabilities & ARR_Missing) return Missing; @@ -3690,7 +3850,7 @@ ASTReader::ReadASTCore(StringRef FileName, ModuleFile &F = *M; BitstreamCursor &Stream = F.Stream; - Stream.init(F.StreamFile); + Stream.init(&F.StreamFile); F.SizeInBits = F.Buffer->getBufferSize() * 8; // Sniff for the signature. @@ -3937,6 +4097,34 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) { } } +static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){ + BitstreamCursor Stream(StreamFile); + if (Stream.Read(8) != 'C' || + Stream.Read(8) != 'P' || + Stream.Read(8) != 'C' || + Stream.Read(8) != 'H') { + return 0; + } + + // Scan for the CONTROL_BLOCK_ID block. + if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) + return 0; + + // Scan for SIGNATURE inside the control block. + ASTReader::RecordData Record; + while (1) { + llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + if (Entry.Kind == llvm::BitstreamEntry::EndBlock || + Entry.Kind != llvm::BitstreamEntry::Record) + return 0; + + Record.clear(); + StringRef Blob; + if (SIGNATURE == Stream.readRecord(Entry.ID, Record, &Blob)) + return Record[0]; + } +} + /// \brief Retrieve the name of the original source file name /// directly from the AST file, without actually loading the AST /// file. @@ -3944,20 +4132,18 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, FileManager &FileMgr, DiagnosticsEngine &Diags) { // Open the AST file. - std::string ErrStr; - std::unique_ptr<llvm::MemoryBuffer> Buffer; - Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr)); + auto Buffer = FileMgr.getBufferForFile(ASTFileName); if (!Buffer) { - Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr; + Diags.Report(diag::err_fe_unable_to_read_pch_file) + << ASTFileName << Buffer.getError().message(); return std::string(); } // Initialize the stream llvm::BitstreamReader StreamFile; - BitstreamCursor Stream; - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - Stream.init(StreamFile); + StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(), + (const unsigned char *)(*Buffer)->getBufferEnd()); + BitstreamCursor Stream(StreamFile); // Sniff for the signature. if (Stream.Read(8) != 'C' || @@ -4012,9 +4198,10 @@ namespace { { } - bool ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain) override { - return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr); + bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, + bool AllowCompatibleDifferences) override { + return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr, + AllowCompatibleDifferences); } bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain) override { @@ -4033,19 +4220,16 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, ASTReaderListener &Listener) { // Open the AST file. - std::string ErrStr; - std::unique_ptr<llvm::MemoryBuffer> Buffer; - Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr)); + auto Buffer = FileMgr.getBufferForFile(Filename); if (!Buffer) { return true; } // Initialize the stream llvm::BitstreamReader StreamFile; - BitstreamCursor Stream; - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - Stream.init(StreamFile); + StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(), + (const unsigned char *)(*Buffer)->getBufferEnd()); + BitstreamCursor Stream(StreamFile); // Sniff for the signature. if (Stream.Read(8) != 'C' || @@ -4061,6 +4245,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, bool NeedsInputFiles = Listener.needsInputFileVisitation(); bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation(); + bool NeedsImports = Listener.needsImportVisitation(); BitstreamCursor InputFilesCursor; if (NeedsInputFiles) { InputFilesCursor = Stream; @@ -4083,6 +4268,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, // Scan for ORIGINAL_FILE inside the control block. RecordData Record; + std::string ModuleDir; while (1) { llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); if (Entry.Kind == llvm::BitstreamEntry::EndBlock) @@ -4107,11 +4293,19 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, case MODULE_NAME: Listener.ReadModuleName(Blob); break; - case MODULE_MAP_FILE: - Listener.ReadModuleMapFile(Blob); + case MODULE_DIRECTORY: + ModuleDir = Blob; break; + case MODULE_MAP_FILE: { + unsigned Idx = 0; + auto Path = ReadString(Record, Idx); + ResolveImportedPath(Path, ModuleDir); + Listener.ReadModuleMapFile(Path); + break; + } case LANGUAGE_OPTIONS: - if (ParseLanguageOptions(Record, false, Listener)) + if (ParseLanguageOptions(Record, false, Listener, + /*AllowCompatibleConfigurationMismatch*/false)) return true; break; @@ -4168,7 +4362,10 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { case INPUT_FILE: bool Overridden = static_cast<bool>(Record[3]); - shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden); + std::string Filename = Blob; + ResolveImportedPath(Filename, ModuleDir); + shouldContinue = + Listener.visitInputFile(Filename, isSystemFile, Overridden); break; } if (!shouldContinue) @@ -4177,6 +4374,21 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, break; } + case IMPORTS: { + if (!NeedsImports) + break; + + unsigned Idx = 0, N = Record.size(); + while (Idx < N) { + // Read information about the AST file. + Idx += 5; // ImportLoc, Size, ModTime, Signature + std::string Filename = ReadString(Record, Idx); + ResolveImportedPath(Filename, ModuleDir); + Listener.visitImport(Filename); + } + break; + } + default: // No other validation to perform. break; @@ -4224,21 +4436,30 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Read a record. StringRef Blob; Record.clear(); - switch (F.Stream.readRecord(Entry.ID, Record, &Blob)) { + auto Kind = F.Stream.readRecord(Entry.ID, Record, &Blob); + + if ((Kind == SUBMODULE_METADATA) != First) { + Error("submodule metadata record should be at beginning of block"); + return Failure; + } + First = false; + + // Submodule information is only valid if we have a current module. + // FIXME: Should we error on these cases? + if (!CurrentModule && Kind != SUBMODULE_METADATA && + Kind != SUBMODULE_DEFINITION) + continue; + + switch (Kind) { default: // Default behavior: ignore. break; - - case SUBMODULE_DEFINITION: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } + case SUBMODULE_DEFINITION: { if (Record.size() < 8) { Error("malformed module definition"); return Failure; } - + StringRef Name = Blob; unsigned Idx = 0; SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]); @@ -4253,20 +4474,17 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { bool ConfigMacrosExhaustive = Record[Idx++]; Module *ParentModule = nullptr; - const FileEntry *ModuleMap = nullptr; - if (Parent) { + 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, ModuleMap, - IsFramework, + CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit).first; + + // FIXME: set the definition loc for CurrentModule, or call + // ModMap.setInferredModuleAllowedBy() + SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; if (GlobalIndex >= SubmodulesLoaded.size() || SubmodulesLoaded[GlobalIndex]) { @@ -4311,14 +4529,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_UMBRELLA_HEADER: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) { if (!CurrentModule->getUmbrellaHeader()) ModMap.setUmbrellaHeader(CurrentModule, Umbrella); @@ -4331,73 +4541,26 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } - case SUBMODULE_HEADER: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - - // We lazily associate headers with their modules via the HeaderInfoTable. - // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead - // of complete filenames or remove it entirely. - break; - } - - case SUBMODULE_EXCLUDED_HEADER: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - - // We lazily associate headers with their modules via the HeaderInfoTable. + case SUBMODULE_HEADER: + case SUBMODULE_EXCLUDED_HEADER: + case SUBMODULE_PRIVATE_HEADER: + // We lazily associate headers with their modules via the HeaderInfo table. // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead // of complete filenames or remove it entirely. - break; - } - - case SUBMODULE_PRIVATE_HEADER: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } + break; - if (!CurrentModule) - break; - - // We lazily associate headers with their modules via the HeaderInfoTable. - // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead - // of complete filenames or remove it entirely. - break; - } + case SUBMODULE_TEXTUAL_HEADER: + case SUBMODULE_PRIVATE_TEXTUAL_HEADER: + // FIXME: Textual headers are not marked in the HeaderInfo table. Load + // them here. + break; case SUBMODULE_TOPHEADER: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - CurrentModule->addTopHeaderFilename(Blob); break; } case SUBMODULE_UMBRELLA_DIR: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - if (const DirectoryEntry *Umbrella = PP.getFileManager().getDirectory(Blob)) { if (!CurrentModule->getUmbrellaDir()) @@ -4412,12 +4575,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_METADATA: { - if (!First) { - Error("submodule metadata record not at beginning of block"); - return Failure; - } - First = false; - F.BaseSubmoduleID = getTotalNumSubmodules(); F.LocalNumSubmodules = Record[0]; unsigned LocalBaseSubmoduleID = Record[1]; @@ -4431,21 +4588,13 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { F.SubmoduleRemap.insertOrReplace( std::make_pair(LocalBaseSubmoduleID, F.BaseSubmoduleID - LocalBaseSubmoduleID)); - + SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules); - } + } break; } case SUBMODULE_IMPORTS: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - for (unsigned Idx = 0; Idx != Record.size(); ++Idx) { UnresolvedModuleRef Unresolved; Unresolved.File = &F; @@ -4459,14 +4608,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_EXPORTS: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; Unresolved.File = &F; @@ -4483,53 +4624,21 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } case SUBMODULE_REQUIRES: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - CurrentModule->addRequirement(Blob, Record[0], Context.getLangOpts(), Context.getTargetInfo()); break; } case SUBMODULE_LINK_LIBRARY: - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - CurrentModule->LinkLibraries.push_back( Module::LinkLibrary(Blob, Record[0])); break; case SUBMODULE_CONFIG_MACRO: - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - CurrentModule->ConfigMacros.push_back(Blob.str()); break; case SUBMODULE_CONFLICT: { - if (First) { - Error("missing submodule metadata record at beginning of block"); - return Failure; - } - - if (!CurrentModule) - break; - UnresolvedModuleRef Unresolved; Unresolved.File = &F; Unresolved.Mod = CurrentModule; @@ -4553,7 +4662,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { /// \returns true if the listener deems the file unacceptable, false otherwise. bool ASTReader::ParseLanguageOptions(const RecordData &Record, bool Complain, - ASTReaderListener &Listener) { + ASTReaderListener &Listener, + bool AllowCompatibleDifferences) { LangOptions LangOpts; unsigned Idx = 0; #define LANGOPT(Name, Bits, Default, Description) \ @@ -4561,7 +4671,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++])); #include "clang/Basic/LangOptions.def" -#define SANITIZER(NAME, ID) LangOpts.Sanitize.ID = Record[Idx++]; +#define SANITIZER(NAME, ID) \ + LangOpts.Sanitize.set(SanitizerKind::ID, Record[Idx++]); #include "clang/Basic/Sanitizers.def" ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++]; @@ -4581,7 +4692,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, } LangOpts.CommentOpts.ParseAllComments = Record[Idx++]; - return Listener.ReadLanguageOptions(LangOpts, Complain); + return Listener.ReadLanguageOptions(LangOpts, Complain, + AllowCompatibleDifferences); } bool ASTReader::ParseTargetOptions(const RecordData &Record, @@ -5235,17 +5347,19 @@ QualType ASTReader::readTypeRecord(unsigned Index) { /*produces*/ Record[5]); unsigned Idx = 6; - unsigned NumParams = Record[Idx++]; - SmallVector<QualType, 16> ParamTypes; - for (unsigned I = 0; I != NumParams; ++I) - ParamTypes.push_back(readType(*Loc.F, Record, Idx)); EPI.Variadic = Record[Idx++]; EPI.HasTrailingReturn = Record[Idx++]; EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]); SmallVector<QualType, 8> ExceptionStorage; - readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx); + readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx); + + unsigned NumParams = Record[Idx++]; + SmallVector<QualType, 16> ParamTypes; + for (unsigned I = 0; I != NumParams; ++I) + ParamTypes.push_back(readType(*Loc.F, Record, Idx)); + return Context.getFunctionType(ResultType, ParamTypes, EPI); } @@ -5414,13 +5528,18 @@ 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. - const Type *T; - if (const Type *Existing = D->getTypeForDecl()) - T = Existing; - else if (auto *Prev = D->getPreviousDecl()) - T = Prev->getTypeForDecl(); - else + const Type *T = nullptr; + for (auto *DI = D; DI; DI = DI->getPreviousDecl()) { + if (const Type *Existing = DI->getTypeForDecl()) { + T = Existing; + break; + } + } + if (!T) { T = new (Context, TypeAlignment) InjectedClassNameType(D, TST); + for (auto *DI = D; DI; DI = DI->getPreviousDecl()) + DI->setTypeForDecl(T); + } return QualType(T, 0); } @@ -5508,24 +5627,22 @@ QualType ASTReader::readTypeRecord(unsigned Index) { void ASTReader::readExceptionSpec(ModuleFile &ModuleFile, SmallVectorImpl<QualType> &Exceptions, - FunctionProtoType::ExtProtoInfo &EPI, + FunctionProtoType::ExceptionSpecInfo &ESI, const RecordData &Record, unsigned &Idx) { ExceptionSpecificationType EST = static_cast<ExceptionSpecificationType>(Record[Idx++]); - EPI.ExceptionSpecType = EST; + ESI.Type = EST; if (EST == EST_Dynamic) { - EPI.NumExceptions = Record[Idx++]; - for (unsigned I = 0; I != EPI.NumExceptions; ++I) + for (unsigned I = 0, N = Record[Idx++]; I != N; ++I) Exceptions.push_back(readType(ModuleFile, Record, Idx)); - EPI.Exceptions = Exceptions.data(); + ESI.Exceptions = Exceptions; } else if (EST == EST_ComputedNoexcept) { - EPI.NoexceptExpr = ReadExpr(ModuleFile); + ESI.NoexceptExpr = ReadExpr(ModuleFile); } else if (EST == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); - EPI.ExceptionSpecTemplate = - ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + ESI.SourceTemplate = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); } else if (EST == EST_Unevaluated) { - EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); } } @@ -5976,18 +6093,10 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { 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 + // FIXME: Merging a function definition should merge // all mergeable entities within it. if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) || isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) { @@ -6000,6 +6109,9 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { updateOutOfDateIdentifier(*II); } else DC->lookup(Name); + } else if (needsAnonymousDeclarationNumber(cast<NamedDecl>(D))) { + // FIXME: It'd be nice to do something a bit more targeted here. + D->getDeclContext()->decls_begin(); } } } @@ -6345,13 +6457,13 @@ namespace { /// declaration context. class DeclContextNameLookupVisitor { ASTReader &Reader; - SmallVectorImpl<const DeclContext *> &Contexts; + ArrayRef<const DeclContext *> Contexts; DeclarationName Name; SmallVectorImpl<NamedDecl *> &Decls; public: - DeclContextNameLookupVisitor(ASTReader &Reader, - SmallVectorImpl<const DeclContext *> &Contexts, + DeclContextNameLookupVisitor(ASTReader &Reader, + ArrayRef<const DeclContext *> Contexts, DeclarationName Name, SmallVectorImpl<NamedDecl *> &Decls) : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { } @@ -6364,9 +6476,9 @@ namespace { // this context in this module. ModuleFile::DeclContextInfosMap::iterator Info; bool FoundInfo = false; - for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) { - Info = M.DeclContextInfos.find(This->Contexts[I]); - if (Info != M.DeclContextInfos.end() && + for (auto *DC : This->Contexts) { + Info = M.DeclContextInfos.find(DC); + if (Info != M.DeclContextInfos.end() && Info->second.NameLookupTableData) { FoundInfo = true; break; @@ -6375,7 +6487,7 @@ namespace { if (!FoundInfo) return false; - + // Look for this name within this module. ASTDeclContextNameLookupTable *LookupTable = Info->second.NameLookupTableData; @@ -6396,9 +6508,11 @@ namespace { // currently read before reading its name. The lookup is triggered by // building that decl (likely indirectly), and so it is later in the // sense of "already existing" and can be ignored here. + // FIXME: This should not happen; deserializing declarations should + // not perform lookups since that can lead to deserialization cycles. continue; } - + // Record this declaration. FoundAnything = true; This->Decls.push_back(ND); @@ -6438,15 +6552,17 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, if (!Name) return false; + Deserializing LookupResults(this); + SmallVector<NamedDecl *, 64> Decls; - + // Compute the declaration contexts we need to look into. Multiple such // declaration contexts occur when two declaration contexts from disjoint // modules get merged, e.g., when two namespaces with the same name are // independently defined in separate modules. SmallVector<const DeclContext *, 2> Contexts; Contexts.push_back(DC); - + if (DC->isNamespace()) { auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); if (Merged != MergedDecls.end()) { @@ -6454,24 +6570,45 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, 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); + auto LookUpInContexts = [&](ArrayRef<const DeclContext*> Contexts) { + DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); - // If we can definitively determine which module file to look into, - // only look there. Otherwise, look in all module files. - ModuleFile *Definitive; - if (Contexts.size() == 1 && - (Definitive = getDefinitiveModuleFileFor(DC, *this))) { - DeclContextNameLookupVisitor::visit(*Definitive, &Visitor); - } else { - ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); + // If we can definitively determine which module file to look into, + // only look there. Otherwise, look in all module files. + ModuleFile *Definitive; + if (Contexts.size() == 1 && + (Definitive = getDefinitiveModuleFileFor(Contexts[0], *this))) { + DeclContextNameLookupVisitor::visit(*Definitive, &Visitor); + } else { + ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); + } + }; + + LookUpInContexts(Contexts); + + // If this might be an implicit special member function, then also search + // all merged definitions of the surrounding class. We need to search them + // individually, because finding an entity in one of them doesn't imply that + // we can't find a different entity in another one. + if (isa<CXXRecordDecl>(DC)) { + auto Kind = Name.getNameKind(); + if (Kind == DeclarationName::CXXConstructorName || + Kind == DeclarationName::CXXDestructorName || + (Kind == DeclarationName::CXXOperatorName && + Name.getCXXOverloadedOperator() == OO_Equal)) { + auto Merged = MergedLookups.find(DC); + if (Merged != MergedLookups.end()) { + for (unsigned I = 0; I != Merged->second.size(); ++I) { + LookUpInContexts(Merged->second[I]); + // We might have just added some more merged lookups. If so, our + // iterator is now invalid, so grab a fresh one before continuing. + Merged = MergedLookups.find(DC); + } + } + } } + ++NumVisibleDeclContextsRead; SetExternalVisibleDeclsForName(DC, Name, Decls); return !Decls.empty(); @@ -6786,11 +6923,11 @@ void ASTReader::InitializeSema(Sema &S) { // Makes sure any declarations that were deserialized "too early" // still get added to the identifier's declaration chains. - for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) { - pushExternalDeclIntoScope(PreloadedDecls[I], - PreloadedDecls[I]->getDeclName()); + for (uint64_t ID : PreloadedDeclIDs) { + NamedDecl *D = cast<NamedDecl>(GetDecl(ID)); + pushExternalDeclIntoScope(D, D->getDeclName()); } - PreloadedDecls.clear(); + PreloadedDeclIDs.clear(); // FIXME: What happens if these are changed by a module import? if (!FPPragmaOptions.empty()) { @@ -6924,15 +7061,18 @@ namespace clang { namespace serialization { unsigned PriorGeneration; unsigned InstanceBits; unsigned FactoryBits; + bool InstanceHasMoreThanOneDecl; + bool FactoryHasMoreThanOneDecl; SmallVector<ObjCMethodDecl *, 4> InstanceMethods; SmallVector<ObjCMethodDecl *, 4> FactoryMethods; public: - ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, + ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, unsigned PriorGeneration) - : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration), - InstanceBits(0), FactoryBits(0) { } - + : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration), + InstanceBits(0), FactoryBits(0), InstanceHasMoreThanOneDecl(false), + FactoryHasMoreThanOneDecl(false) {} + static bool visit(ModuleFile &M, void *UserData) { ReadMethodPoolVisitor *This = static_cast<ReadMethodPoolVisitor *>(UserData); @@ -6966,6 +7106,8 @@ namespace clang { namespace serialization { This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end()); This->InstanceBits = Data.InstanceBits; This->FactoryBits = Data.FactoryBits; + This->InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl; + This->FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl; return true; } @@ -6981,6 +7123,10 @@ namespace clang { namespace serialization { unsigned getInstanceBits() const { return InstanceBits; } unsigned getFactoryBits() const { return FactoryBits; } + bool instanceHasMoreThanOneDecl() const { + return InstanceHasMoreThanOneDecl; + } + bool factoryHasMoreThanOneDecl() const { return FactoryHasMoreThanOneDecl; } }; } } // end namespace clang::serialization @@ -7015,11 +7161,17 @@ void ASTReader::ReadMethodPool(Selector Sel) { Sema &S = *getSema(); Sema::GlobalMethodPool::iterator Pos = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first; - - addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); - addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); + Pos->second.first.setBits(Visitor.getInstanceBits()); + Pos->second.first.setHasMoreThanOneDecl(Visitor.instanceHasMoreThanOneDecl()); Pos->second.second.setBits(Visitor.getFactoryBits()); + Pos->second.second.setHasMoreThanOneDecl(Visitor.factoryHasMoreThanOneDecl()); + + // Add methods to the global pool *after* setting hasMoreThanOneDecl, since + // when building a module we keep every method individually and may need to + // update hasMoreThanOneDecl as we add the methods. + addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); + addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); } void ASTReader::ReadKnownNamespaces( @@ -7095,6 +7247,18 @@ void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) { DynamicClasses.clear(); } +void ASTReader::ReadUnusedLocalTypedefNameCandidates( + llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) { + for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N; + ++I) { + TypedefNameDecl *D = dyn_cast_or_null<TypedefNameDecl>( + GetDecl(UnusedLocalTypedefNameCandidates[I])); + if (D) + Decls.insert(D); + } + UnusedLocalTypedefNameCandidates.clear(); +} + void ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) { for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) { @@ -7230,24 +7394,26 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, } for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { - NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); - if (SemaObj) { - // If we're simply supposed to record the declarations, do so now. - if (Decls) { - Decls->push_back(D); - continue; - } - - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - pushExternalDeclIntoScope(D, II); - } else { + if (!SemaObj) { // Queue this declaration so that it will be added to the // translation unit scope and identifier's declaration chain // once a Sema object is known. - PreloadedDecls.push_back(D); + PreloadedDeclIDs.push_back(DeclIDs[I]); + continue; } + + NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); + + // If we're simply supposed to record the declarations, do so now. + if (Decls) { + Decls->push_back(D); + continue; + } + + // Introduce this declaration into the translation-unit scope + // and add it to the declaration chain for this identifier, so + // that (unqualified) name lookup will find it. + pushExternalDeclIntoScope(D, II); } } @@ -7584,8 +7750,7 @@ ASTReader::ReadTemplateArgument(ModuleFile &F, return TemplateArgument(readType(F, Record, Idx)); case TemplateArgument::Declaration: { ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx); - bool ForReferenceParam = Record[Idx++]; - return TemplateArgument(D, ForReferenceParam); + return TemplateArgument(D, readType(F, Record, Idx)); } case TemplateArgument::NullPtr: return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true); @@ -7806,6 +7971,12 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F, // No associated value, and there can't be a prefix. break; } + + case NestedNameSpecifier::Super: { + CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx); + NNS = NestedNameSpecifier::SuperSpecifier(Context, RD); + break; + } } Prev = NNS; } @@ -7862,9 +8033,16 @@ ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, Builder.MakeGlobal(Context, ColonColonLoc); break; } + + case NestedNameSpecifier::Super: { + CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx); + SourceRange Range = ReadSourceRange(F, Record, Idx); + Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd()); + break; + } } } - + return Builder.getWithLocInContext(Context); } @@ -7906,6 +8084,13 @@ std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) { return Result; } +std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record, + unsigned &Idx) { + std::string Filename = ReadString(Record, Idx); + ResolveImportedPath(F, Filename); + return Filename; +} + VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, unsigned &Idx) { unsigned Major = Record[Idx++]; @@ -8008,6 +8193,14 @@ void ASTReader::ReadComments() { } } +void ASTReader::getInputFiles(ModuleFile &F, + SmallVectorImpl<serialization::InputFile> &Files) { + for (unsigned I = 0, E = F.InputFilesLoaded.size(); I != E; ++I) { + unsigned ID = I+1; + Files.push_back(getInputFile(F, ID)); + } +} + std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { // If we know the owning module, use it. if (Module *M = D->getOwningModule()) @@ -8025,7 +8218,7 @@ void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty() || !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingUpdateRecords.empty() || !PendingOdrMergeChecks.empty()) { + !PendingUpdateRecords.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > @@ -8073,14 +8266,16 @@ void ASTReader::finishPendingActions() { for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; - if (Info.M->Kind != MK_Module) + if (Info.M->Kind != MK_ImplicitModule && + Info.M->Kind != MK_ExplicitModule) resolvePendingMacro(II, Info); } // Handle module imports. for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; - if (Info.M->Kind == MK_Module) + if (Info.M->Kind == MK_ImplicitModule || + Info.M->Kind == MK_ExplicitModule) resolvePendingMacro(II, Info); } } @@ -8097,110 +8292,36 @@ void ASTReader::finishPendingActions() { } // 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()) { + while (!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. - while (!PendingOdrMergeChecks.empty()) { - NamedDecl *D = PendingOdrMergeChecks.pop_back_val(); - - // FIXME: Skip over implicit declarations for now. This matters for things - // like implicitly-declared special member functions. This isn't entirely - // correct; we can end up with multiple unmerged declarations of the same - // implicit entity. - if (D->isImplicit()) - continue; - - DeclContext *CanonDef = D->getDeclContext(); - DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName()); - - bool Found = false; - const Decl *DCanon = D->getCanonicalDecl(); - - llvm::SmallVector<const NamedDecl*, 4> Candidates; - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); - !Found && I != E; ++I) { - 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) - Found = true; - else - Candidates.push_back(cast<NamedDecl>(RI)); - break; - } - } - } - - if (!Found) { - D->setInvalidDecl(); - - std::string CanonDefModule = - getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); - Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) - << D << getOwningModuleNameForDiagnostic(D) - << CanonDef << CanonDefModule.empty() << CanonDefModule; - - if (Candidates.empty()) - Diag(cast<Decl>(CanonDef)->getLocation(), - diag::note_module_odr_violation_no_possible_decls) << D; - else { - for (unsigned I = 0, N = Candidates.size(); I != N; ++I) - Diag(Candidates[I]->getLocation(), - diag::note_module_odr_violation_possible_decl) - << Candidates[I]; - } - - DiagnosedOdrMergeFailures.insert(CanonDef); - } - } } // If we deserialized any C++ or Objective-C class definitions, any // Objective-C protocol definitions, or any redeclarable templates, make sure // that all redeclarations point to the definitions. Note that this can only // happen now, after the redeclaration chains have been fully wired. - for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(), - DEnd = PendingDefinitions.end(); - D != DEnd; ++D) { - if (TagDecl *TD = dyn_cast<TagDecl>(*D)) { + for (Decl *D : PendingDefinitions) { + if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 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 (auto RD = dyn_cast<CXXRecordDecl>(*D)) { - for (auto R : RD->redecls()) + if (auto RD = dyn_cast<CXXRecordDecl>(D)) { + for (auto R : RD->redecls()) { + assert((R == D) == R->isThisDeclarationADefinition() && + "declaration thinks it's the definition but it isn't"); cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData; + } } continue; } - if (auto 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; @@ -8211,14 +8332,14 @@ void ASTReader::finishPendingActions() { continue; } - if (auto PD = dyn_cast<ObjCProtocolDecl>(*D)) { + if (auto PD = dyn_cast<ObjCProtocolDecl>(D)) { for (auto R : PD->redecls()) R->Data = PD->Data; continue; } - auto RTD = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); + auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl(); for (auto R : RTD->redecls()) R->Common = RTD->Common; } @@ -8243,10 +8364,108 @@ void ASTReader::finishPendingActions() { MD->setLazyBody(PB->second); } PendingBodies.clear(); +} + +void ASTReader::diagnoseOdrViolations() { + if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty()) + return; + + // Trigger the import of the full definition of each class that had any + // odr-merging problems, so we can produce better diagnostics for them. + // These updates may in turn find and diagnose some ODR failures, so take + // ownership of the set first. + auto OdrMergeFailures = std::move(PendingOdrMergeFailures); + PendingOdrMergeFailures.clear(); + for (auto &Merge : OdrMergeFailures) { + 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. + // + // Caution: this loop does things that might invalidate iterators into + // PendingOdrMergeChecks. Don't turn this into a range-based for loop! + while (!PendingOdrMergeChecks.empty()) { + NamedDecl *D = PendingOdrMergeChecks.pop_back_val(); + + // FIXME: Skip over implicit declarations for now. This matters for things + // like implicitly-declared special member functions. This isn't entirely + // correct; we can end up with multiple unmerged declarations of the same + // implicit entity. + if (D->isImplicit()) + continue; + + DeclContext *CanonDef = D->getDeclContext(); + + bool Found = false; + const Decl *DCanon = D->getCanonicalDecl(); + + for (auto RI : D->redecls()) { + if (RI->getLexicalDeclContext() == CanonDef) { + Found = true; + break; + } + } + if (Found) + continue; + + llvm::SmallVector<const NamedDecl*, 4> Candidates; + DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName()); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); + !Found && I != E; ++I) { + 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) + Found = true; + else + Candidates.push_back(cast<NamedDecl>(RI)); + break; + } + } + } + + if (!Found) { + // The AST doesn't like TagDecls becoming invalid after they've been + // completed. We only really need to mark FieldDecls as invalid here. + if (!isa<TagDecl>(D)) + D->setInvalidDecl(); + + std::string CanonDefModule = + getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); + Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) + << D << getOwningModuleNameForDiagnostic(D) + << CanonDef << CanonDefModule.empty() << CanonDefModule; + + if (Candidates.empty()) + Diag(cast<Decl>(CanonDef)->getLocation(), + diag::note_module_odr_violation_no_possible_decls) << D; + else { + for (unsigned I = 0, N = Candidates.size(); I != N; ++I) + Diag(Candidates[I]->getLocation(), + diag::note_module_odr_violation_possible_decl) + << Candidates[I]; + } + + DiagnosedOdrMergeFailures.insert(CanonDef); + } + } // Issue any pending ODR-failure diagnostics. - for (auto &Merge : PendingOdrMergeFailures) { - if (!DiagnosedOdrMergeFailures.insert(Merge.first)) + for (auto &Merge : OdrMergeFailures) { + // If we've already pointed out a specific problem with this class, don't + // bother issuing a general "something's different" diagnostic. + if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) continue; bool Diagnosed = false; @@ -8282,7 +8501,6 @@ void ASTReader::finishPendingActions() { << Merge.first; } } - PendingOdrMergeFailures.clear(); } void ASTReader::FinishedDeserializing() { @@ -8295,10 +8513,13 @@ void ASTReader::FinishedDeserializing() { } --NumCurrentElementsDeserializing; - if (NumCurrentElementsDeserializing == 0 && Consumer) { + if (NumCurrentElementsDeserializing == 0) { + diagnoseOdrViolations(); + // We are not in recursive loading, so it's safe to pass the "interesting" // decls to the consumer. - PassInterestingDeclsToConsumer(); + if (Consumer) + PassInterestingDeclsToConsumer(); } } |