diff options
Diffstat (limited to 'lib/Serialization')
-rw-r--r-- | lib/Serialization/ASTCommon.cpp | 18 | ||||
-rw-r--r-- | lib/Serialization/ASTCommon.h | 13 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 1341 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 630 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderInternals.h | 11 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 195 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 883 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 160 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 140 | ||||
-rw-r--r-- | lib/Serialization/GlobalModuleIndex.cpp | 25 | ||||
-rw-r--r-- | lib/Serialization/Module.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ModuleManager.cpp | 84 |
12 files changed, 2397 insertions, 1105 deletions
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index ad046ffa277a8..13393225b60ee 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "ASTCommon.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Serialization/ASTDeserializationListener.h" @@ -150,7 +151,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { switch (static_cast<Decl::Kind>(Kind)) { case Decl::TranslationUnit: // Special case of a "merged" declaration. case Decl::Namespace: - case Decl::NamespaceAlias: // FIXME: Not yet redeclarable, but will be. + case Decl::NamespaceAlias: case Decl::Typedef: case Decl::TypeAlias: case Decl::Enum: @@ -188,8 +189,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::MSProperty: case Decl::ObjCIvar: case Decl::ObjCAtDefsField: - case Decl::ImplicitParam: - case Decl::ParmVar: case Decl::NonTypeTemplateParm: case Decl::TemplateTemplateParm: case Decl::Using: @@ -212,7 +211,20 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::Import: case Decl::OMPThreadPrivate: return false; + + // These indirectly derive from Redeclarable<T> but are not actually + // redeclarable. + case Decl::ImplicitParam: + case Decl::ParmVar: + return false; } llvm_unreachable("Unhandled declaration kind"); } + +bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { + if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext())) + return false; + return isa<TagDecl>(D) || isa<FieldDecl>(D); +} + diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index c7669749260bf..38a0ff5fbd4e4 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H -#define LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H +#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H +#define LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H #include "clang/AST/ASTContext.h" #include "clang/Serialization/ASTBitCodes.h" @@ -25,14 +25,15 @@ enum DeclUpdateKind { UPD_CXX_ADDED_IMPLICIT_MEMBER, UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, + UPD_CXX_ADDED_FUNCTION_DEFINITION, UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, - UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION, UPD_CXX_INSTANTIATED_CLASS_DEFINITION, UPD_CXX_RESOLVED_EXCEPTION_SPEC, UPD_CXX_DEDUCED_RETURN_TYPE, UPD_DECL_MARKED_USED, UPD_MANGLING_NUMBER, - UPD_STATIC_LOCAL_NUMBER + UPD_STATIC_LOCAL_NUMBER, + UPD_DECL_MARKED_OPENMP_THREADPRIVATE }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); @@ -80,6 +81,10 @@ const DeclContext *getDefinitiveDeclContext(const DeclContext *DC); /// \brief Determine whether the given declaration kind is redeclarable. bool isRedeclarableDeclKind(unsigned Kind); +/// \brief Determine whether the given declaration needs an anonymous +/// declaration number. +bool needsAnonymousDeclarationNumber(const NamedDecl *D); + } // namespace serialization } // namespace clang diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index ae41654904c68..416164ebb7d24 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/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(); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 9ed1bf97ec7a5..a783183d2ef6e 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -43,6 +43,9 @@ namespace clang { const RecordData &Record; unsigned &Idx; TypeID TypeIDForTypeDecl; + unsigned AnonymousDeclNumber; + GlobalDeclID NamedDeclForTagDecl; + IdentifierInfo *TypedefNameForLinkage; bool HasPendingBody; @@ -106,6 +109,12 @@ namespace clang { void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &NewDD); + static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, + DeclContext *DC, + unsigned Index); + static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, + unsigned Index, NamedDecl *D); + /// \brief RAII class used to capture the first ID within a redeclaration /// chain and to introduce it into the list of pending redeclaration chains /// on destruction. @@ -134,7 +143,7 @@ namespace clang { ~RedeclarableResult() { if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) && - Reader.PendingDeclChainsKnown.insert(FirstID)) + Reader.PendingDeclChainsKnown.insert(FirstID).second) Reader.PendingDeclChains.push_back(FirstID); } @@ -158,50 +167,59 @@ namespace clang { NamedDecl *New; NamedDecl *Existing; mutable bool AddResult; - + + unsigned AnonymousDeclNumber; + IdentifierInfo *TypedefNameForLinkage; + void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION; - + public: FindExistingResult(ASTReader &Reader) - : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false) {} + : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false), + AnonymousDeclNumber(0), TypedefNameForLinkage(0) {} + + FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing, + unsigned AnonymousDeclNumber, + IdentifierInfo *TypedefNameForLinkage) + : Reader(Reader), New(New), Existing(Existing), AddResult(true), + AnonymousDeclNumber(AnonymousDeclNumber), + TypedefNameForLinkage(TypedefNameForLinkage) {} - FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing) - : Reader(Reader), New(New), Existing(Existing), AddResult(true) { } - FindExistingResult(const FindExistingResult &Other) - : Reader(Other.Reader), New(Other.New), Existing(Other.Existing), - AddResult(Other.AddResult) - { + : Reader(Other.Reader), New(Other.New), Existing(Other.Existing), + AddResult(Other.AddResult), + AnonymousDeclNumber(Other.AnonymousDeclNumber), + TypedefNameForLinkage(Other.TypedefNameForLinkage) { Other.AddResult = false; } - + ~FindExistingResult(); - + /// \brief Suppress the addition of this result into the known set of /// names. void suppress() { AddResult = false; } - + operator NamedDecl*() const { return Existing; } - + template<typename T> operator T*() const { return dyn_cast_or_null<T>(Existing); } }; - + FindExistingResult findExisting(NamedDecl *D); - + public: - ASTDeclReader(ASTReader &Reader, ModuleFile &F, - DeclID thisDeclID, - unsigned RawLocation, - const RecordData &Record, unsigned &Idx) - : Reader(Reader), F(F), ThisDeclID(thisDeclID), - RawLocation(RawLocation), Record(Record), Idx(Idx), - TypeIDForTypeDecl(0), HasPendingBody(false) { } + ASTDeclReader(ASTReader &Reader, ModuleFile &F, DeclID thisDeclID, + unsigned RawLocation, const RecordData &Record, unsigned &Idx) + : Reader(Reader), F(F), ThisDeclID(thisDeclID), + RawLocation(RawLocation), Record(Record), Idx(Idx), + TypeIDForTypeDecl(0), NamedDeclForTagDecl(0), + TypedefNameForLinkage(nullptr), HasPendingBody(false) {} template <typename DeclT> - static void attachPreviousDeclImpl(Redeclarable<DeclT> *D, Decl *Previous); - static void attachPreviousDeclImpl(...); - static void attachPreviousDecl(Decl *D, Decl *previous); + static void attachPreviousDeclImpl(ASTReader &Reader, + Redeclarable<DeclT> *D, Decl *Previous); + static void attachPreviousDeclImpl(ASTReader &Reader, ...); + static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous); template <typename DeclT> static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest); @@ -233,7 +251,7 @@ namespace clang { void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); - void VisitTypedefNameDecl(TypedefNameDecl *TD); + RedeclarableResult VisitTypedefNameDecl(TypedefNameDecl *TD); void VisitTypedefDecl(TypedefDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); @@ -359,6 +377,12 @@ void ASTDeclReader::Visit(Decl *D) { if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { // We have a fully initialized TypeDecl. Read its type now. TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); + + // If this is a tag declaration with a typedef name for linkage, it's safe + // to load that typedef now. + if (NamedDeclForTagDecl) + cast<TagDecl>(D)->NamedDeclOrQualifier = + cast<NamedDecl>(Reader.GetDecl(NamedDeclForTagDecl)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); @@ -446,6 +470,8 @@ void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { VisitDecl(ND); ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx)); + if (needsAnonymousDeclarationNumber(ND)) + AnonymousDeclNumber = Record[Idx++]; } void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { @@ -455,7 +481,8 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); } -void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx); @@ -464,15 +491,21 @@ void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { TD->setModedTypeSourceInfo(TInfo, modedT); } else TD->setTypeSourceInfo(TInfo); - mergeRedeclarable(TD, Redecl); + return Redecl; } void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { - VisitTypedefNameDecl(TD); + RedeclarableResult Redecl = VisitTypedefNameDecl(TD); + mergeRedeclarable(TD, Redecl); } void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { - VisitTypedefNameDecl(TD); + RedeclarableResult Redecl = VisitTypedefNameDecl(TD); + if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>(Record, Idx)) + // Merged when we merge the template. + TD->setDescribedAliasTemplate(Template); + else + mergeRedeclarable(TD, Redecl); } ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { @@ -481,18 +514,32 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { TD->IdentifierNamespace = Record[Idx++]; TD->setTagKind((TagDecl::TagKind)Record[Idx++]); - TD->setCompleteDefinition(Record[Idx++]); + if (!isa<CXXRecordDecl>(TD)) + TD->setCompleteDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setFreeStanding(Record[Idx++]); TD->setCompleteDefinitionRequired(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); - if (Record[Idx++]) { // hasExtInfo + switch (Record[Idx++]) { + case 0: + break; + case 1: { // ExtInfo TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); TD->NamedDeclOrQualifier = Info; - } else - TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx); + break; + } + case 2: // TypedefNameForAnonDecl + NamedDeclForTagDecl = ReadDeclID(Record, Idx); + TypedefNameForLinkage = Reader.GetIdentifierInfo(F, Record, Idx); + break; + case 3: // DeclaratorForAnonDecl + NamedDeclForTagDecl = ReadDeclID(Record, Idx); + break; + default: + llvm_unreachable("unexpected tag info kind"); + } if (!isa<CXXRecordDecl>(TD)) mergeRedeclarable(TD, Redecl); @@ -953,8 +1000,15 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { VisitDeclaratorDecl(FD); FD->Mutable = Record[Idx++]; if (int BitWidthOrInitializer = Record[Idx++]) { - FD->InitializerOrBitWidth.setInt(BitWidthOrInitializer - 1); - FD->InitializerOrBitWidth.setPointer(Reader.ReadExpr(F)); + FD->InitStorage.setInt( + static_cast<FieldDecl::InitStorageKind>(BitWidthOrInitializer - 1)); + if (FD->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) { + // Read captured variable length array. + FD->InitStorage.setPointer( + Reader.readType(F, Record, Idx).getAsOpaquePtr()); + } else { + FD->InitStorage.setPointer(Reader.ReadExpr(F)); + } } if (!FD->getDeclName()) { if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx)) @@ -1140,7 +1194,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx); - if (F.Kind != MK_Module) + if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) D->setAnonymousNamespace(Anon); } else { // Link this namespace back to the first declaration, which has already @@ -1152,11 +1206,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); D->NamespaceLoc = ReadSourceLocation(Record, Idx); D->IdentLoc = ReadSourceLocation(Record, Idx); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); D->Namespace = ReadDeclAs<NamedDecl>(Record, Idx); + mergeRedeclarable(D, Redecl); } void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { @@ -1168,6 +1224,7 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { D->setTypename(Record[Idx++]); if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx)) Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); + mergeMergeable(D); } void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { @@ -1195,6 +1252,7 @@ void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { D->setUsingLoc(ReadSourceLocation(Record, Idx)); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); + mergeMergeable(D); } void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( @@ -1202,6 +1260,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( VisitTypeDecl(D); D->TypenameLocation = ReadSourceLocation(Record, Idx); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + mergeMergeable(D); } void ASTDeclReader::ReadCXXDefinitionData( @@ -1279,6 +1338,7 @@ void ASTDeclReader::ReadCXXDefinitionData( LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]); switch (Kind) { case LCK_This: + case LCK_VLAType: *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation()); break; case LCK_ByCopy: @@ -1300,8 +1360,11 @@ void ASTDeclReader::MergeDefinitionData( // If the new definition has new special members, let the name lookup // code know that it needs to look in the new definition too. - if ((MergeDD.DeclaredSpecialMembers & ~DD.DeclaredSpecialMembers) && - DD.Definition != MergeDD.Definition) { + // + // FIXME: We only need to do this if the merged definition declares members + // that this definition did not declare, or if it defines members that this + // definition did not define. + if (MergeDD.DeclaredSpecialMembers && DD.Definition != MergeDD.Definition) { Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition); DD.Definition->setHasExternalVisibleStorage(); } @@ -1493,12 +1556,19 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { VisitFunctionDecl(D); + unsigned NumOverridenMethods = Record[Idx++]; - while (NumOverridenMethods--) { - // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, - // MD may be initializing. - if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx)) - Reader.getContext().addOverriddenMethod(D, MD); + if (D->isCanonicalDecl()) { + while (NumOverridenMethods--) { + // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, + // MD may be initializing. + if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx)) + Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl()); + } + } else { + // We don't care about which declarations this used to override; we get + // the relevant information from the canonical declaration. + Idx += NumOverridenMethods; } } @@ -2015,6 +2085,8 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *D = static_cast<T*>(DBase); T *DCanon = D->getCanonicalDecl(); if (D != DCanon && + // IDs < NUM_PREDEF_DECL_IDS are not loaded from an AST file. + Redecl.getFirstID() >= NUM_PREDEF_DECL_IDS && (!Reader.getContext().getLangOpts().Modules || Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) { // All redeclarations between this declaration and its originally-canonical @@ -2075,6 +2147,9 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, Result); if (auto *DVar = dyn_cast<VarDecl>(DPattern)) return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result); + if (auto *DAlias = dyn_cast<TypeAliasDecl>(DPattern)) + return mergeRedeclarable(DAlias, cast<TypedefNameDecl>(ExistingPattern), + Result); llvm_unreachable("merged an unknown kind of redeclarable template"); } @@ -2199,7 +2274,8 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) { if (isa<FileScopeAsmDecl>(D) || isa<ObjCProtocolDecl>(D) || isa<ObjCImplDecl>(D) || - isa<ImportDecl>(D)) + isa<ImportDecl>(D) || + isa<OMPThreadPrivateDecl>(D)) return true; if (VarDecl *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && @@ -2269,6 +2345,53 @@ static bool isSameTemplateParameter(const NamedDecl *X, TY->getTemplateParameters()); } +static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) { + if (auto *NS = X->getAsNamespace()) + return NS; + if (auto *NAS = X->getAsNamespaceAlias()) + return NAS->getNamespace(); + return nullptr; +} + +static bool isSameQualifier(const NestedNameSpecifier *X, + const NestedNameSpecifier *Y) { + if (auto *NSX = getNamespace(X)) { + auto *NSY = getNamespace(Y); + if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl()) + return false; + } else if (X->getKind() != Y->getKind()) + return false; + + // FIXME: For namespaces and types, we're permitted to check that the entity + // is named via the same tokens. We should probably do so. + switch (X->getKind()) { + case NestedNameSpecifier::Identifier: + if (X->getAsIdentifier() != Y->getAsIdentifier()) + return false; + break; + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + // We've already checked that we named the same namespace. + break; + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (X->getAsType()->getCanonicalTypeInternal() != + Y->getAsType()->getCanonicalTypeInternal()) + return false; + break; + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: + return true; + } + + // Recurse into earlier portion of NNS, if any. + auto *PX = X->getPrefix(); + auto *PY = Y->getPrefix(); + if (PX && PY) + return isSameQualifier(PX, PY); + return !PX && !PY; +} + /// \brief Determine whether two template parameter lists are similar enough /// that they may be used in declarations of the same template. static bool isSameTemplateParameterList(const TemplateParameterList *X, @@ -2286,10 +2409,10 @@ static bool isSameTemplateParameterList(const TemplateParameterList *X, /// \brief Determine whether the two declarations refer to the same entity. static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); - + if (X == Y) return true; - + // Must be in the same context. if (!X->getDeclContext()->getRedeclContext()->Equals( Y->getDeclContext()->getRedeclContext())) @@ -2301,11 +2424,11 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y)) return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), TypedefY->getUnderlyingType()); - + // Must have the same kind. if (X->getKind() != Y->getKind()) return false; - + // Objective-C classes and protocols with the same name always match. if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) return true; @@ -2327,8 +2450,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } // Functions with the same type and linkage match. - // FIXME: This needs to cope with function template specializations, - // merging of prototyped/non-prototyped functions, etc. + // FIXME: This needs to cope with merging of prototyped/non-prototyped + // functions, etc. if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { FunctionDecl *FuncY = cast<FunctionDecl>(Y); return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) && @@ -2361,7 +2484,6 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { // Fields with the same name and the same type match. if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) { FieldDecl *FDY = cast<FieldDecl>(Y); - // FIXME: Diagnose if the types don't match. // FIXME: Also check the bitwidth is odr-equivalent, if any. return X->getASTContext().hasSameType(FDX->getType(), FDY->getType()); } @@ -2377,6 +2499,30 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return USX->getTargetDecl() == USY->getTargetDecl(); } + // Using declarations with the same qualifier match. (We already know that + // the name matches.) + if (auto *UX = dyn_cast<UsingDecl>(X)) { + auto *UY = cast<UsingDecl>(Y); + return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && + UX->hasTypename() == UY->hasTypename() && + UX->isAccessDeclaration() == UY->isAccessDeclaration(); + } + if (auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) { + auto *UY = cast<UnresolvedUsingValueDecl>(Y); + return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && + UX->isAccessDeclaration() == UY->isAccessDeclaration(); + } + if (auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) + return isSameQualifier( + UX->getQualifier(), + cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier()); + + // Namespace alias definitions with the same target match. + if (auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) { + auto *NAY = cast<NamespaceAliasDecl>(Y); + return NAX->getNamespace()->Equals(NAY->getNamespace()); + } + // FIXME: Many other cases to implement. return false; } @@ -2387,8 +2533,14 @@ static DeclContext *getPrimaryContextForMerging(DeclContext *DC) { if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC)) return ND->getOriginalNamespace(); + // There is one tricky case here: if DC is a class with no definition, then + // we're merging a declaration whose definition is added by an update record, + // but we've not yet loaded that update record. In this case, we use the + // canonical declaration for merging until we get a real definition. + // FIXME: When we add a definition, we may need to move the partial lookup + // information from the canonical declaration onto the chosen definition. if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) - return RD->getDefinition(); + return RD->getPrimaryContext(); if (EnumDecl *ED = dyn_cast<EnumDecl>(DC)) return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() @@ -2401,9 +2553,17 @@ ASTDeclReader::FindExistingResult::~FindExistingResult() { if (!AddResult || Existing) return; + DeclarationName Name = New->getDeclName(); DeclContext *DC = New->getDeclContext()->getRedeclContext(); - if (DC->isTranslationUnit() && Reader.SemaObj) { - Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName()); + if (TypedefNameForLinkage) { + Reader.ImportedTypedefNamesForLinkage.insert( + std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New)); + } else if (!Name) { + assert(needsAnonymousDeclarationNumber(New)); + setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(), + AnonymousDeclNumber, New); + } else if (DC->isTranslationUnit() && Reader.SemaObj) { + Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name); } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { // Add the declaration to its redeclaration context so later merging // lookups will find it. @@ -2411,11 +2571,81 @@ ASTDeclReader::FindExistingResult::~FindExistingResult() { } } +/// Find the declaration that should be merged into, given the declaration found +/// by name lookup. If we're merging an anonymous declaration within a typedef, +/// we need a matching typedef, and we merge with the type inside it. +static NamedDecl *getDeclForMerging(NamedDecl *Found, + bool IsTypedefNameForLinkage) { + if (!IsTypedefNameForLinkage) + return Found; + + // If we found a typedef declaration that gives a name to some other + // declaration, then we want that inner declaration. Declarations from + // AST files are handled via ImportedTypedefNamesForLinkage. + if (Found->isFromASTFile()) return 0; + if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) { + if (auto *TT = TND->getTypeSourceInfo()->getType()->getAs<TagType>()) + if (TT->getDecl()->getTypedefNameForAnonDecl() == TND) + return TT->getDecl(); + } + + return 0; +} + +NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, + DeclContext *DC, + unsigned Index) { + // If the lexical context has been merged, look into the now-canonical + // definition. + if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) + DC = Merged; + + // If we've seen this before, return the canonical declaration. + auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + if (Index < Previous.size() && Previous[Index]) + return Previous[Index]; + + // If this is the first time, but we have parsed a declaration of the context, + // build the anonymous declaration list from the parsed declaration. + if (!cast<Decl>(DC)->isFromASTFile()) { + unsigned Index = 0; + for (Decl *LexicalD : DC->decls()) { + auto *ND = dyn_cast<NamedDecl>(LexicalD); + if (!ND || !needsAnonymousDeclarationNumber(ND)) + continue; + if (Previous.size() == Index) + Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl())); + else + Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl()); + ++Index; + } + } + + return Index < Previous.size() ? Previous[Index] : nullptr; +} + +void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader, + DeclContext *DC, unsigned Index, + NamedDecl *D) { + if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) + DC = Merged; + + auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + if (Index >= Previous.size()) + Previous.resize(Index + 1); + if (!Previous[Index]) + Previous[Index] = D; +} + ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { - DeclarationName Name = D->getDeclName(); - if (!Name) { - // Don't bother trying to find unnamed declarations. - FindExistingResult Result(Reader, D, /*Existing=*/nullptr); + DeclarationName Name = TypedefNameForLinkage ? TypedefNameForLinkage + : D->getDeclName(); + + if (!Name && !needsAnonymousDeclarationNumber(D)) { + // Don't bother trying to find unnamed declarations that are in + // unmergeable contexts. + FindExistingResult Result(Reader, D, /*Existing=*/nullptr, + AnonymousDeclNumber, TypedefNameForLinkage); // FIXME: We may still need to pull in the redeclaration chain; there can // be redeclarations via 'decltype'. Result.suppress(); @@ -2426,7 +2656,27 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // necessary merging already. DeclContext *DC = D->getDeclContext()->getRedeclContext(); - if (DC->isTranslationUnit() && Reader.SemaObj) { + if (TypedefNameForLinkage) { + auto It = Reader.ImportedTypedefNamesForLinkage.find( + std::make_pair(DC, TypedefNameForLinkage)); + if (It != Reader.ImportedTypedefNamesForLinkage.end()) + if (isSameEntity(It->second, D)) + return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber, + TypedefNameForLinkage); + // Go on to check in other places in case an existing typedef name + // was not imported. + } + + if (!Name) { + // This is an anonymous declaration that we may need to merge. Look it up + // in its context by number. + assert(needsAnonymousDeclarationNumber(D)); + if (auto *Existing = getAnonymousDeclForMerging( + Reader, D->getLexicalDeclContext(), AnonymousDeclNumber)) + if (isSameEntity(Existing, D)) + return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, + TypedefNameForLinkage); + } else if (DC->isTranslationUnit() && Reader.SemaObj) { IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; // Temporarily consider the identifier to be up-to-date. We don't want to @@ -2455,14 +2705,18 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { for (IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); I != IEnd; ++I) { - if (isSameEntity(*I, D)) - return FindExistingResult(Reader, D, *I); + if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) + if (isSameEntity(Existing, D)) + return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, + TypedefNameForLinkage); } } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { DeclContext::lookup_result R = MergeDC->noload_lookup(Name); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - if (isSameEntity(*I, D)) - return FindExistingResult(Reader, D, *I); + if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) + if (isSameEntity(Existing, D)) + return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, + TypedefNameForLinkage); } } else { // Not in a mergeable context. @@ -2474,29 +2728,78 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // // FIXME: We should do something similar if we merge two definitions of the // same template specialization into the same CXXRecordDecl. - if (Reader.MergedDeclContexts.count(D->getLexicalDeclContext())) + auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext()); + if (MergedDCIt != Reader.MergedDeclContexts.end() && + MergedDCIt->second == D->getDeclContext()) Reader.PendingOdrMergeChecks.push_back(D); - return FindExistingResult(Reader, D, /*Existing=*/nullptr); + return FindExistingResult(Reader, D, /*Existing=*/nullptr, + AnonymousDeclNumber, TypedefNameForLinkage); } template<typename DeclT> -void ASTDeclReader::attachPreviousDeclImpl(Redeclarable<DeclT> *D, +void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, + Redeclarable<DeclT> *D, Decl *Previous) { D->RedeclLink.setPrevious(cast<DeclT>(Previous)); } -void ASTDeclReader::attachPreviousDeclImpl(...) { +namespace clang { +template<> +void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, + Redeclarable<FunctionDecl> *D, + Decl *Previous) { + FunctionDecl *FD = static_cast<FunctionDecl*>(D); + FunctionDecl *PrevFD = cast<FunctionDecl>(Previous); + + FD->RedeclLink.setPrevious(PrevFD); + + // If the previous declaration is an inline function declaration, then this + // declaration is too. + if (PrevFD->IsInline != FD->IsInline) { + // FIXME: [dcl.fct.spec]p4: + // If a function with external linkage is declared inline in one + // translation unit, it shall be declared inline in all translation + // units in which it appears. + // + // Be careful of this case: + // + // module A: + // template<typename T> struct X { void f(); }; + // template<typename T> inline void X<T>::f() {} + // + // module B instantiates the declaration of X<int>::f + // module C instantiates the definition of X<int>::f + // + // If module B and C are merged, we do not have a violation of this rule. + FD->IsInline = true; + } + + // If this declaration has an unresolved exception specification but the + // previous declaration had a resolved one, resolve the exception + // specification now. + auto *FPT = FD->getType()->getAs<FunctionProtoType>(); + auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>(); + if (FPT && PrevFPT && + isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && + !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) { + Reader.Context.adjustExceptionSpec( + FD, PrevFPT->getExtProtoInfo().ExceptionSpec); + } +} +} +void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) { llvm_unreachable("attachPreviousDecl on non-redeclarable declaration"); } -void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *Previous) { +void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, + Decl *Previous) { assert(D && Previous); switch (D->getKind()) { #define ABSTRACT_DECL(TYPE) -#define DECL(TYPE, BASE) \ - case Decl::TYPE: \ - attachPreviousDeclImpl(cast<TYPE##Decl>(D), Previous); \ +#define DECL(TYPE, BASE) \ + case Decl::TYPE: \ + attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous); \ break; #include "clang/AST/DeclNodes.inc" } @@ -2514,32 +2817,6 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *Previous) { // be too. if (Previous->Used) D->Used = true; - - // If the previous declaration is an inline function declaration, then this - // declaration is too. - if (auto *FD = dyn_cast<FunctionDecl>(D)) { - if (cast<FunctionDecl>(Previous)->IsInline != FD->IsInline) { - // FIXME: [dcl.fct.spec]p4: - // If a function with external linkage is declared inline in one - // translation unit, it shall be declared inline in all translation - // units in which it appears. - // - // Be careful of this case: - // - // module A: - // template<typename T> struct X { void f(); }; - // template<typename T> inline void X<T>::f() {} - // - // module B instantiates the declaration of X<int>::f - // module C instantiates the definition of X<int>::f - // - // If module B and C are merged, we do not have a violation of this rule. - // - //if (!FD->IsInline || Previous->getOwningModule()) - // Diag(FD->getLocation(), diag::err_odr_differing_inline); - FD->IsInline = true; - } - } } template<typename DeclT> @@ -2593,11 +2870,11 @@ ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { // Append the stored merged declarations to the merged declarations set. MergedDeclsMap::iterator Pos = MergedDecls.find(Canon); if (Pos == MergedDecls.end()) - Pos = MergedDecls.insert(std::make_pair(Canon, + Pos = MergedDecls.insert(std::make_pair(Canon, SmallVector<DeclID, 2>())).first; Pos->second.append(StoredPos->second.begin(), StoredPos->second.end()); StoredMergedDecls.erase(StoredPos); - + // Sort and uniquify the set of merged declarations. llvm::array_pod_sort(Pos->second.begin(), Pos->second.end()); Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()), @@ -2927,13 +3204,13 @@ namespace { class RedeclChainVisitor { ASTReader &Reader; SmallVectorImpl<DeclID> &SearchDecls; - llvm::SmallPtrSet<Decl *, 16> &Deserialized; + llvm::SmallPtrSetImpl<Decl *> &Deserialized; GlobalDeclID CanonID; SmallVector<Decl *, 4> Chain; public: RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls, - llvm::SmallPtrSet<Decl *, 16> &Deserialized, + llvm::SmallPtrSetImpl<Decl *> &Deserialized, GlobalDeclID CanonID) : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized), CanonID(CanonID) { @@ -3038,7 +3315,7 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { if (Chain[I] == CanonDecl) continue; - ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent); + ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent); MostRecent = Chain[I]; } @@ -3052,7 +3329,7 @@ namespace { ASTReader &Reader; serialization::GlobalDeclID InterfaceID; ObjCInterfaceDecl *Interface; - llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized; + llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized; unsigned PreviousGeneration; ObjCCategoryDecl *Tail; llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; @@ -3100,7 +3377,7 @@ namespace { ObjCCategoriesVisitor(ASTReader &Reader, serialization::GlobalDeclID InterfaceID, ObjCInterfaceDecl *Interface, - llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized, + llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, unsigned PreviousGeneration) : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface), Deserialized(Deserialized), PreviousGeneration(PreviousGeneration), @@ -3168,13 +3445,80 @@ void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor); } +namespace { +/// Iterator over the redeclarations of a declaration that have already +/// been merged into the same redeclaration chain. +template<typename DeclT> +class MergedRedeclIterator { + DeclT *Start, *Canonical, *Current; +public: + MergedRedeclIterator() : Current(nullptr) {} + MergedRedeclIterator(DeclT *Start) + : Start(Start), Canonical(nullptr), Current(Start) {} + + DeclT *operator*() { return Current; } + + MergedRedeclIterator &operator++() { + if (Current->isFirstDecl()) { + Canonical = Current; + Current = Current->getMostRecentDecl(); + } else + Current = Current->getPreviousDecl(); + + // If we started in the merged portion, we'll reach our start position + // eventually. Otherwise, we'll never reach it, but the second declaration + // we reached was the canonical declaration, so stop when we see that one + // again. + if (Current == Start || Current == Canonical) + Current = nullptr; + return *this; + } + + friend bool operator!=(const MergedRedeclIterator &A, + const MergedRedeclIterator &B) { + return A.Current != B.Current; + } +}; +} +template<typename DeclT> +llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) { + return llvm::iterator_range<MergedRedeclIterator<DeclT>>( + MergedRedeclIterator<DeclT>(D), + MergedRedeclIterator<DeclT>()); +} + +template<typename DeclT, typename Fn> +static void forAllLaterRedecls(DeclT *D, Fn F) { + F(D); + + // Check whether we've already merged D into its redeclaration chain. + // MostRecent may or may not be nullptr if D has not been merged. If + // not, walk the merged redecl chain and see if it's there. + auto *MostRecent = D->getMostRecentDecl(); + bool Found = false; + for (auto *Redecl = MostRecent; Redecl && !Found; + Redecl = Redecl->getPreviousDecl()) + Found = (Redecl == D); + + // If this declaration is merged, apply the functor to all later decls. + if (Found) { + for (auto *Redecl = MostRecent; Redecl != D; + Redecl = Redecl->getPreviousDecl()) + F(Redecl); + } +} + void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, const RecordData &Record) { while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { + // FIXME: If we also have an update record for instantiating the + // definition of D, we need that to happen before we get here. Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx); assert(MD && "couldn't read decl from update record"); + // FIXME: We should call addHiddenDecl instead, to add the member + // to its DeclContext. cast<CXXRecordDecl>(D)->addedMember(MD); break; } @@ -3191,7 +3535,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. - if (ModuleFile.Kind != MK_Module) { + if (ModuleFile.Kind != MK_ImplicitModule && + ModuleFile.Kind != MK_ExplicitModule) { if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) TU->setAnonymousNamespace(Anon); else @@ -3205,7 +3550,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; - case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: { + case UPD_CXX_ADDED_FUNCTION_DEFINITION: { FunctionDecl *FD = cast<FunctionDecl>(D); if (Reader.PendingBodies[FD]) { // FIXME: Maybe check for ODR violations. @@ -3217,17 +3562,18 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // Maintain AST consistency: any later redeclarations of this function // are inline if this one is. (We might have merged another declaration // into this one.) - for (auto *D = FD->getMostRecentDecl(); /**/; - D = D->getPreviousDecl()) { - D->setImplicitlyInline(); - if (D == FD) - break; - } + forAllLaterRedecls(FD, [](FunctionDecl *FD) { + FD->setImplicitlyInline(); + }); } FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx)); if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) std::tie(CD->CtorInitializers, CD->NumCtorInitializers) = Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx); + if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) + // FIXME: Check consistency. + DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile, + Record, Idx)); // Store the offset of the body so we can lazily load it later. Reader.PendingBodies[FD] = GetCurrentCursorOffset(); HasPendingBody = true; @@ -3246,6 +3592,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor, std::make_pair(LexicalOffset, 0), ModuleFile.DeclContextInfos[RD]); + Reader.PendingDefinitions.insert(RD); } auto TSK = (TemplateSpecializationKind)Record[Idx++]; @@ -3267,7 +3614,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); auto *TemplArgList = TemplateArgumentList::CreateCopy( Reader.getContext(), TemplArgs.data(), TemplArgs.size()); - Spec->setInstantiationOf(PartialSpec, TemplArgList); + + // FIXME: If we already have a partial specialization set, + // check that it matches. + if (!Spec->getSpecializedTemplateOrPartial() + .is<ClassTemplatePartialSpecializationDecl *>()) + Spec->setInstantiationOf(PartialSpec, TemplArgList); } } @@ -3285,20 +3637,35 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, } case UPD_CXX_RESOLVED_EXCEPTION_SPEC: { - auto *FD = cast<FunctionDecl>(D); - auto *FPT = FD->getType()->castAs<FunctionProtoType>(); - auto EPI = FPT->getExtProtoInfo(); + // FIXME: This doesn't send the right notifications if there are + // ASTMutationListeners other than an ASTWriter. + FunctionProtoType::ExceptionSpecInfo ESI; SmallVector<QualType, 8> ExceptionStorage; - Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx); - FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(), - FPT->getParamTypes(), EPI)); + Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx); + for (auto *Redecl : merged_redecls(D)) { + auto *FD = cast<FunctionDecl>(Redecl); + auto *FPT = FD->getType()->castAs<FunctionProtoType>(); + if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { + // AST invariant: if any exception spec in the redecl chain is + // resolved, all are resolved. We don't need to go any further. + // FIXME: If the exception spec is resolved, check that it matches. + break; + } + FD->setType(Reader.Context.getFunctionType( + FPT->getReturnType(), FPT->getParamTypes(), + FPT->getExtProtoInfo().withExceptionSpec(ESI))); + } break; } case UPD_CXX_DEDUCED_RETURN_TYPE: { - FunctionDecl *FD = cast<FunctionDecl>(D); - Reader.Context.adjustDeducedFunctionResultType( - FD, Reader.readType(ModuleFile, Record, Idx)); + // FIXME: Also do this when merging redecls. + QualType DeducedResultType = Reader.readType(ModuleFile, Record, Idx); + for (auto *Redecl : merged_redecls(D)) { + // FIXME: If the return type is already deduced, check that it matches. + FunctionDecl *FD = cast<FunctionDecl>(Redecl); + Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType); + } break; } @@ -3306,17 +3673,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // FIXME: This doesn't send the right notifications if there are // ASTMutationListeners other than an ASTWriter. - // FIXME: We can't both pull in declarations (and thus create new pending - // redeclaration chains) *and* walk redeclaration chains in this function. - // We should defer the updates that require walking redecl chains. - // Maintain AST consistency: any later redeclarations are used too. - for (auto *Redecl = D->getMostRecentDecl(); /**/; - Redecl = Redecl->getPreviousDecl()) { - Redecl->Used = true; - if (Redecl == D) - break; - } + forAllLaterRedecls(D, [](Decl *D) { D->Used = true; }); break; } @@ -3327,6 +3685,10 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_STATIC_LOCAL_NUMBER: Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]); break; + case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: + D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( + Reader.Context, ReadSourceRange(Record, Idx))); + break; } } } diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h index a63e362eb64f0..d1b032b27ac22 100644 --- a/lib/Serialization/ASTReaderInternals.h +++ b/lib/Serialization/ASTReaderInternals.h @@ -10,8 +10,8 @@ // This file provides internal definitions used in the AST reader. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H -#define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H +#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H +#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H #include "clang/AST/DeclarationName.h" #include "clang/Serialization/ASTBitCodes.h" @@ -156,6 +156,8 @@ public: SelectorID ID; unsigned InstanceBits; unsigned FactoryBits; + bool InstanceHasMoreThanOneDecl; + bool FactoryHasMoreThanOneDecl; SmallVector<ObjCMethodDecl *, 2> Instance; SmallVector<ObjCMethodDecl *, 2> Factory; }; @@ -194,8 +196,8 @@ typedef llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait> /// /// The on-disk hash table contains a mapping from each header path to /// information about that header (how many times it has been included, its -/// controlling macro, etc.). Note that we actually hash based on the -/// filename, and support "deep" comparisons of file names based on current +/// controlling macro, etc.). Note that we actually hash based on the size +/// and mtime, and support "deep" comparisons of file names based on current /// inode numbers, so that the search can cope with non-normalized path names /// and symlinks. class HeaderFileInfoTrait { @@ -211,6 +213,7 @@ public: off_t Size; time_t ModTime; const char *Filename; + bool Imported; }; typedef const internal_key_type &internal_key_ref; diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 8bf17d51b3e88..4ef2e73062a5b 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -135,8 +135,8 @@ void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) { while (NumStmts--) Stmts.push_back(Reader.ReadSubStmt()); S->setStmts(Reader.getContext(), Stmts.data(), Stmts.size()); - S->setLBracLoc(ReadSourceLocation(Record, Idx)); - S->setRBracLoc(ReadSourceLocation(Record, Idx)); + S->LBraceLoc = ReadSourceLocation(Record, Idx); + S->RBraceLoc = ReadSourceLocation(Record, Idx); } void ASTStmtReader::VisitSwitchCase(SwitchCase *S) { @@ -422,7 +422,8 @@ void ASTStmtReader::VisitExpr(Expr *E) { void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { VisitExpr(E); E->setLocation(ReadSourceLocation(Record, Idx)); - E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]); + E->Type = (PredefinedExpr::IdentType)Record[Idx++]; + E->FnName = cast_or_null<StringLiteral>(Reader.ReadSubExpr()); } void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { @@ -432,7 +433,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.HasFoundDecl = Record[Idx++]; E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record[Idx++]; E->DeclRefExprBits.HadMultipleCandidates = Record[Idx++]; - E->DeclRefExprBits.RefersToEnclosingLocal = Record[Idx++]; + E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record[Idx++]; unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record[Idx++]; @@ -634,7 +635,7 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { unsigned NumBaseSpecs = Record[Idx++]; assert(NumBaseSpecs == E->path_size()); E->setSubExpr(Reader.ReadSubExpr()); - E->setCastKind((CastExpr::CastKind)Record[Idx++]); + E->setCastKind((CastKind)Record[Idx++]); CastExpr::path_iterator BaseI = E->path_begin(); while (NumBaseSpecs--) { CXXBaseSpecifier *BaseSpec = new (Reader.getContext()) CXXBaseSpecifier; @@ -1579,12 +1580,26 @@ void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { E->setExtendingDecl(VD, ManglingNumber); } +void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) { + VisitExpr(E); + E->LParenLoc = ReadSourceLocation(Record, Idx); + E->EllipsisLoc = ReadSourceLocation(Record, Idx); + E->RParenLoc = ReadSourceLocation(Record, Idx); + E->SubExprs[0] = Reader.ReadSubExpr(); + E->SubExprs[1] = Reader.ReadSubExpr(); + E->Opcode = (BinaryOperatorKind)Record[Idx++]; +} + void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); E->SourceExpr = Reader.ReadSubExpr(); E->Loc = ReadSourceLocation(Record, Idx); } +void ASTStmtReader::VisitTypoExpr(TypoExpr *E) { + llvm_unreachable("Cannot read TypoExpr nodes"); +} + //===----------------------------------------------------------------------===// // Microsoft Expressions and Statements //===----------------------------------------------------------------------===// @@ -1715,6 +1730,21 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_mergeable: C = new (Context) OMPMergeableClause(); break; + case OMPC_read: + C = new (Context) OMPReadClause(); + break; + case OMPC_write: + C = new (Context) OMPWriteClause(); + break; + case OMPC_update: + C = new (Context) OMPUpdateClause(); + break; + case OMPC_capture: + C = new (Context) OMPCaptureClause(); + break; + case OMPC_seq_cst: + C = new (Context) OMPSeqCstClause(); + break; case OMPC_private: C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]); break; @@ -1809,6 +1839,16 @@ void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {} void OMPClauseReader::VisitOMPMergeableClause(OMPMergeableClause *) {} +void OMPClauseReader::VisitOMPReadClause(OMPReadClause *) {} + +void OMPClauseReader::VisitOMPWriteClause(OMPWriteClause *) {} + +void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {} + +void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {} + +void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {} + void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); @@ -1817,6 +1857,10 @@ void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setPrivateCopies(Vars); } void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { @@ -1827,6 +1871,14 @@ void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setPrivateCopies(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setInits(Vars); } void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) { @@ -1936,6 +1988,45 @@ void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { E->setAssociatedStmt(Reader.ReadSubStmt()); } +void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) { + VisitStmt(D); + // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. + Idx += 2; + VisitOMPExecutableDirective(D); + D->setIterationVariable(Reader.ReadSubExpr()); + D->setLastIteration(Reader.ReadSubExpr()); + D->setCalcLastIteration(Reader.ReadSubExpr()); + D->setPreCond(Reader.ReadSubExpr()); + auto Fst = Reader.ReadSubExpr(); + auto Snd = Reader.ReadSubExpr(); + D->setCond(Fst, Snd); + D->setInit(Reader.ReadSubExpr()); + D->setInc(Reader.ReadSubExpr()); + if (isOpenMPWorksharingDirective(D->getDirectiveKind())) { + D->setIsLastIterVariable(Reader.ReadSubExpr()); + D->setLowerBoundVariable(Reader.ReadSubExpr()); + D->setUpperBoundVariable(Reader.ReadSubExpr()); + D->setStrideVariable(Reader.ReadSubExpr()); + D->setEnsureUpperBound(Reader.ReadSubExpr()); + D->setNextLowerBound(Reader.ReadSubExpr()); + D->setNextUpperBound(Reader.ReadSubExpr()); + } + SmallVector<Expr *, 4> Sub; + unsigned CollapsedNum = D->getCollapsedNumber(); + Sub.reserve(CollapsedNum); + for (unsigned i = 0; i < CollapsedNum; ++i) + Sub.push_back(Reader.ReadSubExpr()); + D->setCounters(Sub); + Sub.clear(); + for (unsigned i = 0; i < CollapsedNum; ++i) + Sub.push_back(Reader.ReadSubExpr()); + D->setUpdates(Sub); + Sub.clear(); + for (unsigned i = 0; i < CollapsedNum; ++i) + Sub.push_back(Reader.ReadSubExpr()); + D->setFinals(Sub); +} + void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { VisitStmt(D); // The NumClauses field was read in ReadStmtFromStream. @@ -1944,17 +2035,15 @@ void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { } void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) { - VisitStmt(D); - // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. - Idx += 2; - VisitOMPExecutableDirective(D); + VisitOMPLoopDirective(D); } void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) { - VisitStmt(D); - // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. - Idx += 2; - VisitOMPExecutableDirective(D); + VisitOMPLoopDirective(D); +} + +void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) { + VisitOMPLoopDirective(D); } void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) { @@ -1988,10 +2077,12 @@ void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) { } void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { - VisitStmt(D); - // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. - Idx += 2; - VisitOMPExecutableDirective(D); + VisitOMPLoopDirective(D); +} + +void ASTStmtReader::VisitOMPParallelForSimdDirective( + OMPParallelForSimdDirective *D) { + VisitOMPLoopDirective(D); } void ASTStmtReader::VisitOMPParallelSectionsDirective( @@ -2031,6 +2122,35 @@ void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); + D->setX(Reader.ReadSubExpr()); + D->setV(Reader.ReadSubExpr()); + D->setExpr(Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2529,6 +2649,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } + case STMT_OMP_FOR_SIMD_DIRECTIVE: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPForSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum, + Empty); + break; + } + case STMT_OMP_SECTIONS_DIRECTIVE: S = OMPSectionsDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); @@ -2559,6 +2687,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } + case STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPParallelForSimdDirective::CreateEmpty(Context, NumClauses, + CollapsedNum, Empty); + break; + } + case STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE: S = OMPParallelSectionsDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); @@ -2586,6 +2722,25 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_ORDERED_DIRECTIVE: + S = OMPOrderedDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_ATOMIC_DIRECTIVE: + S = OMPAtomicDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + + case STMT_OMP_TARGET_DIRECTIVE: + S = OMPTargetDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + + case STMT_OMP_TEAMS_DIRECTIVE: + S = OMPTeamsDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; @@ -2775,7 +2930,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_MATERIALIZE_TEMPORARY: S = new (Context) MaterializeTemporaryExpr(Empty); break; - + + case EXPR_CXX_FOLD: + S = new (Context) CXXFoldExpr(Empty); + break; + case EXPR_OPAQUE_VALUE: S = new (Context) OpaqueValueExpr(Empty); break; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 0f52a9fd04085..6c60d45503de8 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -51,6 +51,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include <algorithm> #include <cstdio> #include <string.h> @@ -83,6 +84,8 @@ namespace { public: /// \brief Type code that corresponds to the record generated. TypeCode Code; + /// \brief Abbreviation to use for the record, if any. + unsigned AbbrevToUse; ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record) : Writer(Writer), Record(Record), Code(TYPE_EXT_QUAL) { } @@ -190,6 +193,9 @@ void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { // FIXME: need to stabilize encoding of calling convention... Record.push_back(C.getCC()); Record.push_back(C.getProducesResult()); + + if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult()) + AbbrevToUse = 0; } void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { @@ -216,14 +222,21 @@ static void addExceptionSpec(ASTWriter &Writer, const FunctionProtoType *T, void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { VisitFunctionType(T); - Record.push_back(T->getNumParams()); - for (unsigned I = 0, N = T->getNumParams(); I != N; ++I) - Writer.AddTypeRef(T->getParamType(I), Record); + Record.push_back(T->isVariadic()); Record.push_back(T->hasTrailingReturn()); Record.push_back(T->getTypeQuals()); Record.push_back(static_cast<unsigned>(T->getRefQualifier())); addExceptionSpec(Writer, T, Record); + + Record.push_back(T->getNumParams()); + for (unsigned I = 0, N = T->getNumParams(); I != N; ++I) + Writer.AddTypeRef(T->getParamType(I), Record); + + if (T->isVariadic() || T->hasTrailingReturn() || T->getTypeQuals() || + T->getRefQualifier() || T->getExceptionSpecType() != EST_None) + AbbrevToUse = 0; + Code = TYPE_FUNCTION_PROTO; } @@ -649,6 +662,40 @@ void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { Writer.AddSourceLocation(TL.getRParenLoc(), Record); } +void ASTWriter::WriteTypeAbbrevs() { + using namespace llvm; + + BitCodeAbbrev *Abv; + + // Abbreviation for TYPE_EXT_QUAL + Abv = new BitCodeAbbrev(); + Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3)); // Quals + TypeExtQualAbbrev = Stream.EmitAbbrev(Abv); + + // Abbreviation for TYPE_FUNCTION_PROTO + Abv = new BitCodeAbbrev(); + Abv->Add(BitCodeAbbrevOp(serialization::TYPE_FUNCTION_PROTO)); + // FunctionType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ReturnType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NoReturn + Abv->Add(BitCodeAbbrevOp(0)); // HasRegParm + Abv->Add(BitCodeAbbrevOp(0)); // RegParm + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC + Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult + // FunctionProtoType + Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic + Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn + Abv->Add(BitCodeAbbrevOp(0)); // TypeQuals + Abv->Add(BitCodeAbbrevOp(0)); // RefQualifier + Abv->Add(BitCodeAbbrevOp(EST_None)); // ExceptionSpec + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumParams + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Params + TypeFunctionProtoAbbrev = Stream.EmitAbbrev(Abv); +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// @@ -684,6 +731,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, #define RECORD(X) EmitRecordID(X, #X, Stream, Record) RECORD(STMT_STOP); RECORD(STMT_NULL_PTR); + RECORD(STMT_REF_PTR); RECORD(STMT_NULL); RECORD(STMT_COMPOUND); RECORD(STMT_CASE); @@ -711,6 +759,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_STRING_LITERAL); RECORD(EXPR_CHARACTER_LITERAL); RECORD(EXPR_PAREN); + RECORD(EXPR_PAREN_LIST); RECORD(EXPR_UNARY_OPERATOR); RECORD(EXPR_SIZEOF_ALIGN_OF); RECORD(EXPR_ARRAY_SUBSCRIPT); @@ -752,8 +801,13 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(STMT_OBJC_AT_SYNCHRONIZED); RECORD(STMT_OBJC_AT_THROW); RECORD(EXPR_OBJC_BOOL_LITERAL); + RECORD(STMT_CXX_CATCH); + RECORD(STMT_CXX_TRY); + RECORD(STMT_CXX_FOR_RANGE); RECORD(EXPR_CXX_OPERATOR_CALL); + RECORD(EXPR_CXX_MEMBER_CALL); RECORD(EXPR_CXX_CONSTRUCT); + RECORD(EXPR_CXX_TEMPORARY_OBJECT); RECORD(EXPR_CXX_STATIC_CAST); RECORD(EXPR_CXX_DYNAMIC_CAST); RECORD(EXPR_CXX_REINTERPRET_CAST); @@ -765,11 +819,10 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_CXX_NULL_PTR_LITERAL); RECORD(EXPR_CXX_TYPEID_EXPR); RECORD(EXPR_CXX_TYPEID_TYPE); - RECORD(EXPR_CXX_UUIDOF_EXPR); - RECORD(EXPR_CXX_UUIDOF_TYPE); RECORD(EXPR_CXX_THIS); RECORD(EXPR_CXX_THROW); RECORD(EXPR_CXX_DEFAULT_ARG); + RECORD(EXPR_CXX_DEFAULT_INIT); RECORD(EXPR_CXX_BIND_TEMPORARY); RECORD(EXPR_CXX_SCALAR_VALUE_INIT); RECORD(EXPR_CXX_NEW); @@ -781,12 +834,22 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT); RECORD(EXPR_CXX_UNRESOLVED_MEMBER); RECORD(EXPR_CXX_UNRESOLVED_LOOKUP); + RECORD(EXPR_CXX_EXPRESSION_TRAIT); RECORD(EXPR_CXX_NOEXCEPT); RECORD(EXPR_OPAQUE_VALUE); + RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR); + RECORD(EXPR_TYPE_TRAIT); + RECORD(EXPR_ARRAY_TYPE_TRAIT); RECORD(EXPR_PACK_EXPANSION); RECORD(EXPR_SIZEOF_PACK); + RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); + RECORD(EXPR_FUNCTION_PARM_PACK); + RECORD(EXPR_MATERIALIZE_TEMPORARY); RECORD(EXPR_CUDA_KERNEL_CALL); + RECORD(EXPR_CXX_UUIDOF_EXPR); + RECORD(EXPR_CXX_UUIDOF_TYPE); + RECORD(EXPR_LAMBDA); #undef RECORD } @@ -800,6 +863,7 @@ void ASTWriter::WriteBlockInfoBlock() { // Control Block. BLOCK(CONTROL_BLOCK); RECORD(METADATA); + RECORD(SIGNATURE); RECORD(MODULE_NAME); RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); @@ -895,15 +959,14 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_VARIABLE_ARRAY); RECORD(TYPE_VECTOR); RECORD(TYPE_EXT_VECTOR); - RECORD(TYPE_FUNCTION_PROTO); RECORD(TYPE_FUNCTION_NO_PROTO); + RECORD(TYPE_FUNCTION_PROTO); RECORD(TYPE_TYPEDEF); RECORD(TYPE_TYPEOF_EXPR); RECORD(TYPE_TYPEOF); RECORD(TYPE_RECORD); RECORD(TYPE_ENUM); RECORD(TYPE_OBJC_INTERFACE); - RECORD(TYPE_OBJC_OBJECT); RECORD(TYPE_OBJC_OBJECT_POINTER); RECORD(TYPE_DECLTYPE); RECORD(TYPE_ELABORATED); @@ -920,8 +983,13 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_PACK_EXPANSION); RECORD(TYPE_ATTRIBUTED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); + RECORD(TYPE_AUTO); + RECORD(TYPE_UNARY_TRANSFORM); RECORD(TYPE_ATOMIC); + RECORD(TYPE_DECAYED); + RECORD(TYPE_ADJUSTED); RECORD(DECL_TYPEDEF); + RECORD(DECL_TYPEALIAS); RECORD(DECL_ENUM); RECORD(DECL_RECORD); RECORD(DECL_ENUM_CONSTANT); @@ -990,42 +1058,76 @@ void ASTWriter::WriteBlockInfoBlock() { Stream.ExitBlock(); } +/// \brief Prepares a path for being written to an AST file by converting it +/// to an absolute path and removing nested './'s. +/// +/// \return \c true if the path was changed. +bool cleanPathForOutput(FileManager &FileMgr, SmallVectorImpl<char> &Path) { + bool Changed = false; + + if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) { + llvm::sys::fs::make_absolute(Path); + Changed = true; + } + + return Changed | FileMgr.removeDotPaths(Path); +} + /// \brief Adjusts the given filename to only write out the portion of the /// filename that is not part of the system root directory. /// /// \param Filename the file name to adjust. /// -/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and -/// the returned filename will be adjusted by this system root. +/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and +/// the returned filename will be adjusted by this root directory. /// /// \returns either the original filename (if it needs no adjustment) or the /// adjusted filename (which points into the @p Filename parameter). static const char * -adjustFilenameForRelocatablePCH(const char *Filename, StringRef isysroot) { +adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) { assert(Filename && "No file name to adjust?"); - if (isysroot.empty()) + if (BaseDir.empty()) return Filename; // Verify that the filename and the system root have the same prefix. unsigned Pos = 0; - for (; Filename[Pos] && Pos < isysroot.size(); ++Pos) - if (Filename[Pos] != isysroot[Pos]) + for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos) + if (Filename[Pos] != BaseDir[Pos]) return Filename; // Prefixes don't match. // We hit the end of the filename before we hit the end of the system root. if (!Filename[Pos]) return Filename; - // If the file name has a '/' at the current position, skip over the '/'. - // We distinguish sysroot-based includes from absolute includes by the - // absence of '/' at the beginning of sysroot-based includes. - if (Filename[Pos] == '/') + // If there's not a path separator at the end of the base directory nor + // immediately after it, then this isn't within the base directory. + if (!llvm::sys::path::is_separator(Filename[Pos])) { + if (!llvm::sys::path::is_separator(BaseDir.back())) + return Filename; + } else { + // If the file name has a '/' at the current position, skip over the '/'. + // We distinguish relative paths from absolute paths by the + // absence of '/' at the beginning of relative paths. + // + // FIXME: This is wrong. We distinguish them by asking if the path is + // absolute, which isn't the same thing. And there might be multiple '/'s + // in a row. Use a better mechanism to indicate whether we have emitted an + // absolute or relative path. ++Pos; + } return Filename + Pos; } +static ASTFileSignature getSignature() { + while (1) { + if (ASTFileSignature S = llvm::sys::Process::GetRandomNumber()) + return S; + // Rely on GetRandomNumber to eventually return non-zero... + } +} + /// \brief Write the control block. void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, @@ -1050,13 +1152,20 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back(VERSION_MINOR); Record.push_back(CLANG_VERSION_MAJOR); Record.push_back(CLANG_VERSION_MINOR); + assert((!WritingModule || isysroot.empty()) && + "writing module as a relocatable PCH?"); Record.push_back(!isysroot.empty()); Record.push_back(ASTHasCompilerErrors); Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); - // Module name + // Signature + Record.clear(); + Record.push_back(getSignature()); + Stream.EmitRecord(SIGNATURE, Record); + if (WritingModule) { + // Module name BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name @@ -1066,19 +1175,46 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name); } - // Module map file - if (WritingModule) { + if (WritingModule && WritingModule->Directory) { + // Module directory. BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(MODULE_MAP_FILE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename + Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); - - assert(WritingModule->ModuleMap && "missing module map"); - SmallString<128> ModuleMap(WritingModule->ModuleMap->getName()); - llvm::sys::fs::make_absolute(ModuleMap); RecordData Record; - Record.push_back(MODULE_MAP_FILE); - Stream.EmitRecordWithBlob(AbbrevCode, Record, ModuleMap.str()); + Record.push_back(MODULE_DIRECTORY); + + SmallString<128> BaseDir(WritingModule->Directory->getName()); + cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir); + Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir); + + // Write out all other paths relative to the base directory if possible. + BaseDirectory.assign(BaseDir.begin(), BaseDir.end()); + } else if (!isysroot.empty()) { + // Write out paths relative to the sysroot if possible. + BaseDirectory = isysroot; + } + + // Module map file + if (WritingModule) { + Record.clear(); + + auto &Map = PP.getHeaderSearchInfo().getModuleMap(); + + // Primary module map file. + AddPath(Map.getModuleMapFileForUniquing(WritingModule)->getName(), Record); + + // Additional module map files. + if (auto *AdditionalModMaps = + Map.getAdditionalModuleMapFiles(WritingModule)) { + Record.push_back(AdditionalModMaps->size()); + for (const FileEntry *F : *AdditionalModMaps) + AddPath(F->getName(), Record); + } else { + Record.push_back(0); + } + + Stream.EmitRecord(MODULE_MAP_FILE, Record); } // Imports @@ -1096,9 +1232,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, AddSourceLocation((*M)->ImportLoc, Record); Record.push_back((*M)->File->getSize()); Record.push_back((*M)->File->getModificationTime()); - const std::string &FileName = (*M)->FileName; - Record.push_back(FileName.size()); - Record.append(FileName.begin(), FileName.end()); + Record.push_back((*M)->Signature); + AddPath((*M)->FileName, Record); } Stream.EmitRecord(IMPORTS, Record); } @@ -1110,8 +1245,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back(LangOpts.Name); #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ Record.push_back(static_cast<unsigned>(LangOpts.get##Name())); -#include "clang/Basic/LangOptions.def" -#define SANITIZER(NAME, ID) Record.push_back(LangOpts.Sanitize.ID); +#include "clang/Basic/LangOptions.def" +#define SANITIZER(NAME, ID) \ + Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID)); #include "clang/Basic/Sanitizers.def" Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind()); @@ -1245,17 +1381,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); - SmallString<128> MainFilePath(MainFile->getName()); - - llvm::sys::fs::make_absolute(MainFilePath); - - const char *MainFileNameStr = MainFilePath.c_str(); - MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, - isysroot); Record.clear(); Record.push_back(ORIGINAL_FILE); Record.push_back(SM.getMainFileID().getOpaqueValue()); - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); + EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName()); } Record.clear(); @@ -1281,7 +1410,6 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, WriteInputFiles(Context.SourceMgr, PP.getHeaderSearchInfo().getHeaderSearchOpts(), - isysroot, PP.getLangOpts().Modules); Stream.ExitBlock(); } @@ -1297,7 +1425,6 @@ namespace { void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, - StringRef isysroot, bool Modules) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); @@ -1368,23 +1495,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, // Whether this file was overridden. Record.push_back(Entry.BufferOverridden); - // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Entry.File->getName(); - SmallString<128> FilePath(Filename); - - // Ask the file manager to fixup the relative path for us. This will - // honor the working directory. - SourceMgr.getFileManager().FixupRelativePath(FilePath); - - // FIXME: This call to make_absolute shouldn't be necessary, the - // call to FixupRelativePath should always return an absolute path. - llvm::sys::fs::make_absolute(FilePath); - Filename = FilePath.c_str(); - - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - - Stream.EmitRecordWithBlob(IFAbbrevCode, Record, Filename); - } + EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); + } Stream.ExitBlock(); @@ -1494,6 +1606,9 @@ namespace { // The hash is based only on size/time of the file, so that the reader can // match even when symlinking or excess path elements ("foo/../", "../") // change the form of the name. However, complete path is still the key. + // + // FIXME: Using the mtime here will cause problems for explicit module + // imports. return llvm::hash_combine(key.FE->getSize(), key.FE->getModificationTime()); } @@ -1574,7 +1689,7 @@ namespace { /// \brief Write the header search block for the list of files that /// /// \param HS The header search structure to save. -void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { +void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); @@ -1598,17 +1713,16 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)) continue; - // Turn the file name into an absolute path, if it isn't already. + // Massage the file path into an appropriate form. const char *Filename = File->getName(); - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - - // If we performed any translation on the file name at all, we need to - // save this string, since the generator will refer to it later. - if (Filename != File->getName()) { - Filename = strdup(Filename); + SmallString<128> FilenameTmp(Filename); + if (PreparePathForOutput(FilenameTmp)) { + // If we performed any translation on the file name at all, we need to + // save this string, since the generator will refer to it later. + Filename = strdup(FilenameTmp.c_str()); SavedStrings.push_back(Filename); } - + HeaderFileInfoTrait::key_type key = { File, Filename }; Generator.insert(key, HFI, GeneratorTrait); ++NumHeaderSearchEntries; @@ -1658,8 +1772,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { /// errors), we probably won't have to create file entries for any of /// the files in the AST. void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP, - StringRef isysroot) { + const Preprocessor &PP) { RecordData Record; // Enter the source manager block. @@ -1808,17 +1921,10 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, LineTableInfo &LineTable = SourceMgr.getLineTable(); Record.clear(); - // Emit the file names + // Emit the file names. Record.push_back(LineTable.getNumFilenames()); - for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { - // Emit the file name - const char *Filename = LineTable.getFilename(I); - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - unsigned FilenameLen = Filename? strlen(Filename) : 0; - Record.push_back(FilenameLen); - if (FilenameLen) - Record.insert(Record.end(), Filename, Filename + FilenameLen); - } + for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) + AddPath(LineTable.getFilename(I), Record); // Emit the line entries for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); @@ -1904,10 +2010,8 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, if (IsModule) { // Re-export any imported directives. - // FIXME: Also ensure we re-export imported #undef directives. - if (auto *DMD = dyn_cast<DefMacroDirective>(MD)) - if (DMD->isImported()) - return false; + if (MD->isImported()) + return false; SourceLocation Loc = MD->getLocation(); if (Loc.isInvalid()) @@ -1986,16 +2090,24 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { AddSourceLocation(MD->getLocation(), Record); Record.push_back(MD->getKind()); - if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) { MacroID InfoID = getMacroRef(DefMD->getInfo(), Name); Record.push_back(InfoID); - Record.push_back(DefMD->isImported()); + Record.push_back(DefMD->getOwningModuleID()); Record.push_back(DefMD->isAmbiguous()); - - } else if (VisibilityMacroDirective * - VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { + } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) { + Record.push_back(UndefMD->getOwningModuleID()); + } else { + auto *VisMD = cast<VisibilityMacroDirective>(MD); Record.push_back(VisMD->isPublic()); } + + if (MD->isImported()) { + auto Overrides = MD->getOverriddenModules(); + Record.push_back(Overrides.size()); + for (auto Override : Overrides) + Record.push_back(Override); + } } if (Record.empty()) continue; @@ -2271,7 +2383,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } // Enter the submodule description block. - Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); + Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5); // Write the abbreviations needed for the submodules block. using namespace llvm; @@ -2322,11 +2434,21 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev); Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(Abbrev); Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name @@ -2398,35 +2520,34 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, UmbrellaDir->getName()); } - + // Emit the headers. - for (unsigned I = 0, N = Mod->NormalHeaders.size(); I != N; ++I) { - Record.clear(); - Record.push_back(SUBMODULE_HEADER); - Stream.EmitRecordWithBlob(HeaderAbbrev, Record, - Mod->NormalHeaders[I]->getName()); - } - // Emit the excluded headers. - for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) { - Record.clear(); - Record.push_back(SUBMODULE_EXCLUDED_HEADER); - Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record, - Mod->ExcludedHeaders[I]->getName()); - } - // Emit the private headers. - for (unsigned I = 0, N = Mod->PrivateHeaders.size(); I != N; ++I) { + struct { + unsigned RecordKind; + unsigned Abbrev; + Module::HeaderKind HeaderKind; + } HeaderLists[] = { + {SUBMODULE_HEADER, HeaderAbbrev, Module::HK_Normal}, + {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Module::HK_Textual}, + {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Module::HK_Private}, + {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev, + Module::HK_PrivateTextual}, + {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded} + }; + for (auto &HL : HeaderLists) { Record.clear(); - Record.push_back(SUBMODULE_PRIVATE_HEADER); - Stream.EmitRecordWithBlob(PrivateHeaderAbbrev, Record, - Mod->PrivateHeaders[I]->getName()); + Record.push_back(HL.RecordKind); + for (auto &H : Mod->Headers[HL.HeaderKind]) + Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten); } - ArrayRef<const FileEntry *> - TopHeaders = Mod->getTopHeaders(PP->getFileManager()); - for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) { + + // Emit the top headers. + { + auto TopHeaders = Mod->getTopHeaders(PP->getFileManager()); Record.clear(); Record.push_back(SUBMODULE_TOPHEADER); - Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, - TopHeaders[I]->getName()); + for (auto *H : TopHeaders) + Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName()); } // Emit the imports. @@ -2434,7 +2555,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Record.clear(); for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) { unsigned ImportedID = getSubmoduleID(Mod->Imports[I]); - assert(ImportedID && "Unknown submodule!"); + assert(ImportedID && "Unknown submodule!"); Record.push_back(ImportedID); } Stream.EmitRecord(SUBMODULE_IMPORTS, Record); @@ -2611,12 +2732,14 @@ void ASTWriter::WriteType(QualType T) { // Emit the type's representation. ASTTypeWriter W(*this, Record); + W.AbbrevToUse = 0; if (T.hasLocalNonFastQualifiers()) { Qualifiers Qs = T.getLocalQualifiers(); AddTypeRef(T.getLocalUnqualifiedType(), Record); Record.push_back(Qs.getAsOpaqueValue()); W.Code = TYPE_EXT_QUAL; + W.AbbrevToUse = TypeExtQualAbbrev; } else { switch (T->getTypeClass()) { // For all of the concrete, non-dependent types, call the @@ -2629,7 +2752,7 @@ void ASTWriter::WriteType(QualType T) { } // Emit the serialized record. - Stream.EmitRecord(W.Code, Record); + Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); // Flush any expressions that were written as part of this type. FlushStmts(); @@ -2772,11 +2895,11 @@ public: unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) - if (Method->Method) + if (Method->getMethod()) DataLen += 4; for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) - if (Method->Method) + if (Method->getMethod()) DataLen += 4; LE.write<uint16_t>(DataLen); return std::make_pair(KeyLen, DataLen); @@ -2806,32 +2929,39 @@ public: unsigned NumInstanceMethods = 0; for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) - if (Method->Method) + if (Method->getMethod()) ++NumInstanceMethods; unsigned NumFactoryMethods = 0; for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) - if (Method->Method) + if (Method->getMethod()) ++NumFactoryMethods; unsigned InstanceBits = Methods.Instance.getBits(); assert(InstanceBits < 4); - unsigned NumInstanceMethodsAndBits = - (NumInstanceMethods << 2) | InstanceBits; + unsigned InstanceHasMoreThanOneDeclBit = + Methods.Instance.hasMoreThanOneDecl(); + unsigned FullInstanceBits = (NumInstanceMethods << 3) | + (InstanceHasMoreThanOneDeclBit << 2) | + InstanceBits; unsigned FactoryBits = Methods.Factory.getBits(); assert(FactoryBits < 4); - unsigned NumFactoryMethodsAndBits = (NumFactoryMethods << 2) | FactoryBits; - LE.write<uint16_t>(NumInstanceMethodsAndBits); - LE.write<uint16_t>(NumFactoryMethodsAndBits); + unsigned FactoryHasMoreThanOneDeclBit = + Methods.Factory.hasMoreThanOneDecl(); + unsigned FullFactoryBits = (NumFactoryMethods << 3) | + (FactoryHasMoreThanOneDeclBit << 2) | + FactoryBits; + LE.write<uint16_t>(FullInstanceBits); + LE.write<uint16_t>(FullFactoryBits); for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) - if (Method->Method) - LE.write<uint32_t>(Writer.getDeclID(Method->Method)); + if (Method->getMethod()) + LE.write<uint32_t>(Writer.getDeclID(Method->getMethod())); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) - if (Method->Method) - LE.write<uint32_t>(Writer.getDeclID(Method->Method)); + if (Method->getMethod()) + LE.write<uint32_t>(Writer.getDeclID(Method->getMethod())); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -2877,19 +3007,19 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { if (Chain && I->second < FirstSelectorID) { // Selector already exists. Did it change? bool changed = false; - for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method; - M = M->getNext()) { - if (!M->Method->isFromASTFile()) + for (ObjCMethodList *M = &Data.Instance; + !changed && M && M->getMethod(); M = M->getNext()) { + if (!M->getMethod()->isFromASTFile()) changed = true; } - for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method; + for (ObjCMethodList *M = &Data.Factory; !changed && M && M->getMethod(); M = M->getNext()) { - if (!M->Method->isFromASTFile()) + if (!M->getMethod()->isFromASTFile()) changed = true; } if (!changed) continue; - } else if (Data.Instance.Method || Data.Factory.Method) { + } else if (Data.Instance.getMethod() || Data.Factory.getMethod()) { // A new method pool entry. ++NumTableEntries; } @@ -2995,115 +3125,140 @@ class ASTIdentifierTableTrait { if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) { if (!IsModule) return !shouldIgnoreMacro(Macro, IsModule, PP); - SubmoduleID ModID; - if (getFirstPublicSubmoduleMacro(Macro, ModID)) + + MacroState State; + if (getFirstPublicSubmoduleMacro(Macro, State)) return true; } return false; } - typedef llvm::SmallVectorImpl<SubmoduleID> OverriddenList; + enum class SubmoduleMacroState { + /// We've seen nothing about this macro. + None, + /// We've seen a public visibility directive. + Public, + /// We've either exported a macro for this module or found that the + /// module's definition of this macro is private. + Done + }; + typedef llvm::DenseMap<SubmoduleID, SubmoduleMacroState> MacroState; MacroDirective * - getFirstPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID) { - ModID = 0; - llvm::SmallVector<SubmoduleID, 1> Overridden; - if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden)) - if (!shouldIgnoreMacro(NextMD, IsModule, PP)) - return NextMD; + getFirstPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) { + if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, State)) + return NextMD; return nullptr; } MacroDirective * - getNextPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID, - OverriddenList &Overridden) { + getNextPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) { if (MacroDirective *NextMD = - getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden)) - if (!shouldIgnoreMacro(NextMD, IsModule, PP)) - return NextMD; + getPublicSubmoduleMacro(MD->getPrevious(), State)) + return NextMD; return nullptr; } - /// \brief Traverses the macro directives history and returns the latest - /// public macro definition or undefinition that is not in ModID. + /// \brief Traverses the macro directives history and returns the next + /// public macro definition or undefinition that has not been found so far. + /// /// A macro that is defined in submodule A and undefined in submodule B /// will still be considered as defined/exported from submodule A. - /// ModID is updated to the module containing the returned directive. - /// - /// FIXME: This process breaks down if a module defines a macro, imports - /// another submodule that changes the macro, then changes the - /// macro again itself. MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD, - SubmoduleID &ModID, - OverriddenList &Overridden) { - Overridden.clear(); + MacroState &State) { if (!MD) return nullptr; - SubmoduleID OrigModID = ModID; Optional<bool> IsPublic; for (; MD; MD = MD->getPrevious()) { - SubmoduleID ThisModID = getSubmoduleID(MD); - if (ThisModID == 0) { - IsPublic = Optional<bool>(); - - // If we have no directive location, this macro was installed when - // finalizing the ASTReader. - if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) - if (DefMD->getInfo()->getOwningModuleID()) - return MD; - // Skip imports that only produce #undefs for now. - // FIXME: We should still re-export them! + // Once we hit an ignored macro, we're done: the rest of the chain + // will all be ignored macros. + if (shouldIgnoreMacro(MD, IsModule, PP)) + break; + + // If this macro was imported, re-export it. + if (MD->isImported()) + return MD; + SubmoduleID ModID = getSubmoduleID(MD); + auto &S = State[ModID]; + assert(ModID && "found macro in no submodule"); + + if (S == SubmoduleMacroState::Done) continue; + + if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { + // The latest visibility directive for a name in a submodule affects all + // the directives that come before it. + if (S == SubmoduleMacroState::None) + S = VisMD->isPublic() ? SubmoduleMacroState::Public + : SubmoduleMacroState::Done; + } else { + S = SubmoduleMacroState::Done; + return MD; } - if (ThisModID != ModID) { - ModID = ThisModID; - IsPublic = Optional<bool>(); - } + } + + return nullptr; + } + + ArrayRef<SubmoduleID> + getOverriddenSubmodules(MacroDirective *MD, + SmallVectorImpl<SubmoduleID> &ScratchSpace) { + assert(!isa<VisibilityMacroDirective>(MD) && + "only #define and #undef can override"); + if (MD->isImported()) + return MD->getOverriddenModules(); + + ScratchSpace.clear(); + SubmoduleID ModID = getSubmoduleID(MD); + for (MD = MD->getPrevious(); MD; MD = MD->getPrevious()) { + if (shouldIgnoreMacro(MD, IsModule, PP)) + break; // If this is a definition from a submodule import, that submodule's // definition is overridden by the definition or undefinition that we // started with. - // FIXME: This should only apply to macros defined in OrigModID. - // We can't do that currently, because a #include of a different submodule - // of the same module just leaks through macros instead of providing new - // DefMacroDirectives for them. - if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { - // Figure out which submodule the macro was originally defined within. - SubmoduleID SourceID = DefMD->getInfo()->getOwningModuleID(); - if (!SourceID) { - SourceLocation DefLoc = DefMD->getInfo()->getDefinitionLoc(); - if (DefLoc == MD->getLocation()) - SourceID = ThisModID; - else - SourceID = Writer.inferSubmoduleIDFromLocation(DefLoc); + if (MD->isImported()) { + if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) { + SubmoduleID DefModuleID = DefMD->getInfo()->getOwningModuleID(); + assert(DefModuleID && "imported macro has no owning module"); + ScratchSpace.push_back(DefModuleID); + } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) { + // If we override a #undef, we override anything that #undef overrides. + // We don't need to override it, since an active #undef doesn't affect + // the meaning of a macro. + auto Overrides = UndefMD->getOverriddenModules(); + ScratchSpace.insert(ScratchSpace.end(), + Overrides.begin(), Overrides.end()); } - if (OrigModID && SourceID != OrigModID) - Overridden.push_back(SourceID); } - // We are looking for a definition in a different submodule than the one - // that we started with. If a submodule has re-definitions of the same - // macro, only the last definition will be used as the "exported" one. - if (ModID == OrigModID) - continue; - - // The latest visibility directive for a name in a submodule affects all - // the directives that come before it. - if (VisibilityMacroDirective *VisMD = - dyn_cast<VisibilityMacroDirective>(MD)) { - if (!IsPublic.hasValue()) - IsPublic = VisMD->isPublic(); - } else if (!IsPublic.hasValue() || IsPublic.getValue()) { - // FIXME: If we find an imported macro, we should include its list of - // overrides in our export. - return MD; + // Stop once we leave the original macro's submodule. + // + // Either this submodule #included another submodule of the same + // module or it just happened to be built after the other module. + // In the former case, we override the submodule's macro. + // + // FIXME: In the latter case, we shouldn't do so, but we can't tell + // these cases apart. + // + // FIXME: We can leave this submodule and re-enter it if it #includes a + // header within a different submodule of the same module. In such cases + // the overrides list will be incomplete. + SubmoduleID DirectiveModuleID = getSubmoduleID(MD); + if (DirectiveModuleID != ModID) { + if (DirectiveModuleID && !MD->isImported()) + ScratchSpace.push_back(DirectiveModuleID); + break; } } - return nullptr; + std::sort(ScratchSpace.begin(), ScratchSpace.end()); + ScratchSpace.erase(std::unique(ScratchSpace.begin(), ScratchSpace.end()), + ScratchSpace.end()); + return ScratchSpace; } SubmoduleID getSubmoduleID(MacroDirective *MD) { @@ -3139,27 +3294,23 @@ public: if (hadMacroDefinition(II, Macro)) { DataLen += 4; // MacroDirectives offset. if (IsModule) { - SubmoduleID ModID; - llvm::SmallVector<SubmoduleID, 4> Overridden; - for (MacroDirective * - MD = getFirstPublicSubmoduleMacro(Macro, ModID); - MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) { - // Previous macro's overrides. - if (!Overridden.empty()) - DataLen += 4 * (1 + Overridden.size()); + MacroState State; + SmallVector<SubmoduleID, 16> Scratch; + for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State); + MD; MD = getNextPublicSubmoduleMacro(MD, State)) { DataLen += 4; // MacroInfo ID or ModuleID. + if (unsigned NumOverrides = + getOverriddenSubmodules(MD, Scratch).size()) + DataLen += 4 * (1 + NumOverrides); } - // Previous macro's overrides. - if (!Overridden.empty()) - DataLen += 4 * (1 + Overridden.size()); - DataLen += 4; + DataLen += 4; // 0 terminator. } } for (IdentifierResolver::iterator D = IdResolver.begin(II), DEnd = IdResolver.end(); D != DEnd; ++D) - DataLen += sizeof(DeclID); + DataLen += 4; } using namespace llvm::support; endian::Writer<little> LE(Out); @@ -3186,8 +3337,10 @@ public: using namespace llvm::support; endian::Writer<little> LE(Out); LE.write<uint32_t>(Overridden.size() | 0x80000000U); - for (unsigned I = 0, N = Overridden.size(); I != N; ++I) + for (unsigned I = 0, N = Overridden.size(); I != N; ++I) { + assert(Overridden[I] && "zero module ID for override"); LE.write<uint32_t>(Overridden[I]); + } } } @@ -3219,24 +3372,28 @@ public: LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II)); if (IsModule) { // Write the IDs of macros coming from different submodules. - SubmoduleID ModID; - llvm::SmallVector<SubmoduleID, 4> Overridden; - for (MacroDirective * - MD = getFirstPublicSubmoduleMacro(Macro, ModID); - MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) { - MacroID InfoID = 0; - emitMacroOverrides(Out, Overridden); + MacroState State; + SmallVector<SubmoduleID, 16> Scratch; + for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State); + MD; MD = getNextPublicSubmoduleMacro(MD, State)) { if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { - InfoID = Writer.getMacroID(DefMD->getInfo()); + // FIXME: If this macro directive was created by #pragma pop_macros, + // or if it was created implicitly by resolving conflicting macros, + // it may be for a different submodule from the one in the MacroInfo + // object. If so, we should write out its owning ModuleID. + MacroID InfoID = Writer.getMacroID(DefMD->getInfo()); assert(InfoID); LE.write<uint32_t>(InfoID << 1); } else { - assert(isa<UndefMacroDirective>(MD)); - LE.write<uint32_t>((ModID << 1) | 1); + auto *UndefMD = cast<UndefMacroDirective>(MD); + SubmoduleID Mod = UndefMD->isImported() + ? UndefMD->getOwningModuleID() + : getSubmoduleID(UndefMD); + LE.write<uint32_t>((Mod << 1) | 1); } + emitMacroOverrides(Out, getOverriddenSubmodules(MD, Scratch)); } - emitMacroOverrides(Out, Overridden); - LE.write<uint32_t>(0); + LE.write<uint32_t>(0xdeadbeef); } } @@ -3367,6 +3524,31 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, // DeclContext's Name Lookup Table Serialization //===----------------------------------------------------------------------===// +/// Determine the declaration that should be put into the name lookup table to +/// represent the given declaration in this module. This is usually D itself, +/// but if D was imported and merged into a local declaration, we want the most +/// recent local declaration instead. The chosen declaration will be the most +/// recent declaration in any module that imports this one. +static NamedDecl *getDeclForLocalLookup(NamedDecl *D) { + if (!D->isFromASTFile()) + return D; + + if (Decl *Redecl = D->getPreviousDecl()) { + // For Redeclarable decls, a prior declaration might be local. + for (; Redecl; Redecl = Redecl->getPreviousDecl()) + if (!Redecl->isFromASTFile()) + return cast<NamedDecl>(Redecl); + } else if (Decl *First = D->getCanonicalDecl()) { + // For Mergeable decls, the first decl might be local. + if (!First->isFromASTFile()) + return cast<NamedDecl>(First); + } + + // All declarations are imported. Our most recent declaration will also be + // the most recent one in anyone who imports us. + return D; +} + namespace { // Trait used for the on-disk hash table used in the method pool. class ASTDeclContextNameLookupTrait { @@ -3484,7 +3666,7 @@ public: LE.write<uint16_t>(Lookup.size()); for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end(); I != E; ++I) - LE.write<uint32_t>(Writer.GetDeclRef(*I)); + LE.write<uint32_t>(Writer.GetDeclRef(getDeclForLocalLookup(*I))); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -3524,13 +3706,13 @@ static void visitLocalLookupResults(const DeclContext *ConstDC, } void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) { - if (UpdatedDeclContexts.insert(DC) && WritingAST) { + if (UpdatedDeclContexts.insert(DC).second && WritingAST) { // Ensure we emit all the visible declarations. visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage, [&](DeclarationName Name, DeclContext::lookup_const_result Result) { for (auto *Decl : Result) - GetDeclRef(Decl); + GetDeclRef(getDeclForLocalLookup(Decl)); }); } } @@ -3646,8 +3828,6 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, Record.push_back(BucketOffset); Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, LookupTable.str()); - - Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record); ++NumVisibleDeclContexts; return Offset; } @@ -3729,6 +3909,8 @@ void ASTWriter::WriteRedeclarations() { FirstFromAST = Prev; } + // FIXME: Do we need to do this for the first declaration from each + // redeclaration chain that was merged into this one? Chain->MergedDecls[FirstFromAST].push_back(getDeclID(First)); } @@ -3914,6 +4096,37 @@ void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { Record.insert(Record.end(), Str.begin(), Str.end()); } +bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) { + assert(Context && "should have context when outputting path"); + + bool Changed = + cleanPathForOutput(Context->getSourceManager().getFileManager(), Path); + + // Remove a prefix to make the path relative, if relevant. + const char *PathBegin = Path.data(); + const char *PathPtr = + adjustFilenameForRelocatableAST(PathBegin, BaseDirectory); + if (PathPtr != PathBegin) { + Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin)); + Changed = true; + } + + return Changed; +} + +void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) { + SmallString<128> FilePath(Path); + PreparePathForOutput(FilePath); + AddString(FilePath, Record); +} + +void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record, + StringRef Path) { + SmallString<128> FilePath(Path); + PreparePathForOutput(FilePath); + Stream.EmitRecordWithBlob(Abbrev, Record, FilePath); +} + void ASTWriter::AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record) { Record.push_back(Version.getMajor()); @@ -3950,29 +4163,26 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { } ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) - : Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr), - WritingModule(nullptr), WritingAST(false), DoneWritingDeclsAndTypes(false), - ASTHasCompilerErrors(false), - FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), - FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), - FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), - FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID), - FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), - NextSubmoduleID(FirstSubmoduleID), - FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), - CollectedStmts(&StmtsToEmit), - NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), - NumVisibleDeclContexts(0), - NextCXXBaseSpecifiersID(1), - DeclParmVarAbbrev(0), DeclContextLexicalAbbrev(0), - DeclContextVisibleLookupAbbrev(0), UpdateVisibleAbbrev(0), - DeclRefExprAbbrev(0), CharacterLiteralAbbrev(0), - DeclRecordAbbrev(0), IntegerLiteralAbbrev(0), - DeclTypedefAbbrev(0), - DeclVarAbbrev(0), DeclFieldAbbrev(0), - DeclEnumAbbrev(0), DeclObjCIvarAbbrev(0) -{ -} + : Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr), + WritingModule(nullptr), WritingAST(false), + DoneWritingDeclsAndTypes(false), ASTHasCompilerErrors(false), + FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), + FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), + FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID), + FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), + NextSubmoduleID(FirstSubmoduleID), + FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), + CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), + NumLexicalDeclContexts(0), NumVisibleDeclContexts(0), + NextCXXBaseSpecifiersID(1), TypeExtQualAbbrev(0), + TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0), + DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0), + UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0), + DeclVarAbbrev(0), DeclFieldAbbrev(0), DeclEnumAbbrev(0), + DeclObjCIvarAbbrev(0), DeclCXXMethodAbbrev(0), DeclRefExprAbbrev(0), + CharacterLiteralAbbrev(0), IntegerLiteralAbbrev(0), + ExprImplicitCastAbbrev(0) {} ASTWriter::~ASTWriter() { llvm::DeleteContainerSeconds(FileDeclIDs); @@ -4001,6 +4211,7 @@ void ASTWriter::WriteAST(Sema &SemaRef, Context = nullptr; PP = nullptr; this->WritingModule = nullptr; + this->BaseDirectory.clear(); WritingAST = false; } @@ -4150,6 +4361,11 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } } + // Build a record containing all of the UnusedLocalTypedefNameCandidates. + RecordData UnusedLocalTypedefNameCandidates; + for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) + AddDeclRef(TD, UnusedLocalTypedefNameCandidates); + // Build a record containing all of dynamic classes declarations. RecordData DynamicClasses; AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses); @@ -4316,22 +4532,36 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, SmallString<2048> Buffer; { llvm::raw_svector_ostream Out(Buffer); - for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(), - MEnd = Chain->ModuleMgr.end(); - M != MEnd; ++M) { + for (ModuleFile *M : Chain->ModuleMgr) { using namespace llvm::support; endian::Writer<little> LE(Out); - StringRef FileName = (*M)->FileName; + StringRef FileName = M->FileName; LE.write<uint16_t>(FileName.size()); Out.write(FileName.data(), FileName.size()); - LE.write<uint32_t>((*M)->SLocEntryBaseOffset); - LE.write<uint32_t>((*M)->BaseIdentifierID); - LE.write<uint32_t>((*M)->BaseMacroID); - LE.write<uint32_t>((*M)->BasePreprocessedEntityID); - LE.write<uint32_t>((*M)->BaseSubmoduleID); - LE.write<uint32_t>((*M)->BaseSelectorID); - LE.write<uint32_t>((*M)->BaseDeclID); - LE.write<uint32_t>((*M)->BaseTypeIndex); + + // Note: if a base ID was uint max, it would not be possible to load + // another module after it or have more than one entity inside it. + uint32_t None = std::numeric_limits<uint32_t>::max(); + + auto writeBaseIDOrNone = [&](uint32_t BaseID, bool ShouldWrite) { + assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high"); + if (ShouldWrite) + LE.write<uint32_t>(BaseID); + else + LE.write<uint32_t>(None); + }; + + // These values should be unique within a chain, since they will be read + // as keys into ContinuousRangeMaps. + writeBaseIDOrNone(M->SLocEntryBaseOffset, M->LocalNumSLocEntries); + writeBaseIDOrNone(M->BaseIdentifierID, M->LocalNumIdentifiers); + writeBaseIDOrNone(M->BaseMacroID, M->LocalNumMacros); + writeBaseIDOrNone(M->BasePreprocessedEntityID, + M->NumPreprocessedEntities); + writeBaseIDOrNone(M->BaseSubmoduleID, M->LocalNumSubmodules); + writeBaseIDOrNone(M->BaseSelectorID, M->LocalNumSelectors); + writeBaseIDOrNone(M->BaseDeclID, M->LocalNumDecls); + writeBaseIDOrNone(M->BaseTypeIndex, M->LocalNumTypes); } } Record.clear(); @@ -4344,8 +4574,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Keep writing types, declarations, and declaration update records // until we've emitted all of them. - Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); - WriteDeclsBlockAbbrevs(); + Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); + WriteTypeAbbrevs(); + WriteDeclAbbrevs(); for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(), E = DeclsToRewrite.end(); I != E; ++I) @@ -4371,11 +4602,11 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); WriteCXXBaseSpecifiersOffsets(); WriteFileDeclIDsMap(); - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); + WriteSourceManagerBlock(Context.getSourceManager(), PP); WriteComments(); WritePreprocessor(PP, isModule); - WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); + WriteHeaderSearch(PP.getHeaderSearchInfo()); WriteSelectors(SemaRef); WriteReferencedSelectorsPool(SemaRef); WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); @@ -4423,6 +4654,11 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, if (!DynamicClasses.empty()) Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses); + // Write the record containing potentially unused local typedefs. + if (!UnusedLocalTypedefNameCandidates.empty()) + Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, + UnusedLocalTypedefNameCandidates); + // Write the record containing pending implicit instantiations. if (!PendingInstantiations.empty()) Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); @@ -4469,10 +4705,13 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) { return A.ID < B.ID; }; + auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) { + return A.ID == B.ID; + }; // Sort and deduplicate module IDs. std::sort(Imports.begin(), Imports.end(), Cmp); - Imports.erase(std::unique(Imports.begin(), Imports.end(), Cmp), + Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq), Imports.end()); RecordData ImportedModules; @@ -4532,17 +4771,17 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Record.push_back(GetDeclRef(Update.getDecl())); break; - case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: - AddSourceLocation(Update.getLoc(), Record); - break; - - case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: + case UPD_CXX_ADDED_FUNCTION_DEFINITION: // An updated body is emitted last, so that the reader doesn't need // to skip over the lazy body to reach statements for other records. Record.pop_back(); HasUpdatedBody = true; break; + case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: + AddSourceLocation(Update.getLoc(), Record); + break; + case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast<CXXRecordDecl>(D); AddUpdatedDeclContext(RD->getPrimaryContext()); @@ -4582,8 +4821,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { // Instantiation may change attributes; write them all out afresh. Record.push_back(D->hasAttrs()); if (Record.back()) - WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(), - D->getAttrs().size()), Record); + WriteAttributes(llvm::makeArrayRef(D->getAttrs().begin(), + D->getAttrs().size()), Record); // FIXME: Ensure we don't get here for explicit instantiations. break; @@ -4607,15 +4846,21 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { case UPD_STATIC_LOCAL_NUMBER: Record.push_back(Update.getNumber()); break; + case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: + AddSourceRange(D->getAttr<OMPThreadPrivateDeclAttr>()->getRange(), + Record); + break; } } if (HasUpdatedBody) { const FunctionDecl *Def = cast<FunctionDecl>(D); - Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION); + Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION); Record.push_back(Def->isInlined()); AddSourceLocation(Def->getInnerLocStart(), Record); AddFunctionDefinition(Def, Record); + if (auto *DD = dyn_cast<CXXDestructorDecl>(Def)) + Record.push_back(GetDeclRef(DD->getOperatorDelete())); } OffsetsRecord.push_back(GetDeclRef(D)); @@ -4981,6 +5226,30 @@ void ASTWriter::AddDeclarationName(DeclarationName Name, RecordDataImpl &Record) } } +unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) { + assert(needsAnonymousDeclarationNumber(D) && + "expected an anonymous declaration"); + + // Number the anonymous declarations within this context, if we've not + // already done so. + auto It = AnonymousDeclarationNumbers.find(D); + if (It == AnonymousDeclarationNumbers.end()) { + unsigned Index = 0; + for (Decl *LexicalD : D->getLexicalDeclContext()->decls()) { + auto *ND = dyn_cast<NamedDecl>(LexicalD); + if (!ND || !needsAnonymousDeclarationNumber(ND)) + continue; + AnonymousDeclarationNumbers[ND] = Index++; + } + + It = AnonymousDeclarationNumbers.find(D); + assert(It != AnonymousDeclarationNumbers.end() && + "declaration not found within its lexical context"); + } + + return It->second; +} + void ASTWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, DeclarationName Name, RecordDataImpl &Record) { switch (Name.getNameKind()) { @@ -5068,6 +5337,10 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, case NestedNameSpecifier::Global: // Don't need to write an associated value. break; + + case NestedNameSpecifier::Super: + AddDeclRef(NNS->getAsRecordDecl(), Record); + break; } } } @@ -5117,6 +5390,11 @@ void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, case NestedNameSpecifier::Global: AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); break; + + case NestedNameSpecifier::Super: + AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; } } } @@ -5186,7 +5464,7 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, break; case TemplateArgument::Declaration: AddDeclRef(Arg.getAsDecl(), Record); - Record.push_back(Arg.isDeclForReferenceParam()); + AddTypeRef(Arg.getParamTypeForDecl(), Record); break; case TemplateArgument::NullPtr: AddTypeRef(Arg.getNullPtrType(), Record); @@ -5418,6 +5696,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Capture.getCaptureKind()); switch (Capture.getCaptureKind()) { case LCK_This: + case LCK_VLAType: break; case LCK_ByCopy: case LCK_ByRef: @@ -5521,8 +5800,6 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { } void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { - assert(!WritingAST && "Already writing the AST!"); - // TU and namespaces are handled elsewhere. if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC)) return; @@ -5531,12 +5808,12 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { return; // Not a source decl added to a DeclContext from PCH. assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!"); + assert(!WritingAST && "Already writing the AST!"); AddUpdatedDeclContext(DC); UpdatingVisibleDecls.push_back(D); } void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { - assert(!WritingAST && "Already writing the AST!"); assert(D->isImplicit()); if (!(!D->isFromASTFile() && RD->isFromASTFile())) return; // Not a source member added to a class from PCH. @@ -5545,17 +5822,18 @@ void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { // A decl coming from PCH was modified. assert(RD->isCompleteDefinition()); + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D)); } void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) { // The specializations set is kept in the canonical template. - assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D)); } @@ -5563,11 +5841,11 @@ void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, void ASTWriter::AddedCXXTemplateSpecialization( const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) { // The specializations set is kept in the canonical template. - assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D)); } @@ -5575,11 +5853,11 @@ void ASTWriter::AddedCXXTemplateSpecialization( void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) { // The specializations set is kept in the canonical template. - assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. + assert(!WritingAST && "Already writing the AST!"); DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D)); } @@ -5607,9 +5885,8 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { if (!D->isFromASTFile()) return; // Declaration not imported from PCH. - // Implicit decl from a PCH was defined. - // FIXME: Should implicit definition be a separate FunctionDecl? - RewriteDecl(D); + // Implicit function decl from a PCH was defined. + DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { @@ -5617,10 +5894,8 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { if (!D->isFromASTFile()) return; - // Since the actual instantiation is delayed, this really means that we need - // to update the instantiation location. DeclUpdates[D].push_back( - DeclUpdate(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION)); + DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { @@ -5668,3 +5943,11 @@ void ASTWriter::DeclarationMarkedUsed(const Decl *D) { DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED)); } + +void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) { + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); +} diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 47ce747d5bd3d..4017ec63d4f2c 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -167,8 +167,8 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Record.push_back(D->isInvalidDecl()); Record.push_back(D->hasAttrs()); if (D->hasAttrs()) - Writer.WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(), - D->getAttrs().size()), Record); + Writer.WriteAttributes(llvm::makeArrayRef(D->getAttrs().begin(), + D->getAttrs().size()), Record); Record.push_back(D->isImplicit()); Record.push_back(D->isUsed(false)); Record.push_back(D->isReferenced()); @@ -203,6 +203,8 @@ void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { VisitDecl(D); Writer.AddDeclarationName(D->getDeclName(), Record); + if (needsAnonymousDeclarationNumber(D)) + Record.push_back(Writer.getAnonymousDeclarationNumber(D)); } void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { @@ -224,13 +226,11 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { VisitTypedefNameDecl(D); if (!D->hasAttrs() && !D->isImplicit() && - !D->isUsed(false) && D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && - !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && - D->getAccess() == AS_none && !D->isModulePrivate() && + !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclTypedefAbbrev(); @@ -239,6 +239,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { VisitTypedefNameDecl(D); + Writer.AddDeclRef(D->getDescribedAliasTemplate(), Record); Code = serialization::DECL_TYPEALIAS; } @@ -247,18 +248,26 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); Record.push_back(D->getIdentifierNamespace()); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding - Record.push_back(D->isCompleteDefinition()); + if (!isa<CXXRecordDecl>(D)) + Record.push_back(D->isCompleteDefinition()); Record.push_back(D->isEmbeddedInDeclarator()); Record.push_back(D->isFreeStanding()); Record.push_back(D->isCompleteDefinitionRequired()); Writer.AddSourceLocation(D->getRBraceLoc(), Record); - Record.push_back(D->hasExtInfo()); - if (D->hasExtInfo()) + + if (D->hasExtInfo()) { + Record.push_back(1); Writer.AddQualifierInfo(*D->getExtInfo(), Record); - else if (D->hasDeclaratorForAnonDecl()) - Writer.AddDeclRef(D->getDeclaratorForAnonDecl(), Record); - else - Writer.AddDeclRef(D->getTypedefNameForAnonDecl(), Record); + } else if (auto *TD = D->getTypedefNameForAnonDecl()) { + Record.push_back(2); + Writer.AddDeclRef(TD, Record); + Writer.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo(), Record); + } else if (auto *DD = D->getDeclaratorForAnonDecl()) { + Record.push_back(3); + Writer.AddDeclRef(DD, Record); + } else { + Record.push_back(0); + } } void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { @@ -284,6 +293,8 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && + !D->getTypedefNameForAnonDecl() && + !D->getDeclaratorForAnonDecl() && D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && @@ -293,6 +304,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !CXXRecordDecl::classofKind(D->getKind()) && !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() && + !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclEnumAbbrev(); @@ -310,6 +322,8 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && + !D->getTypedefNameForAnonDecl() && + !D->getDeclaratorForAnonDecl() && D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && @@ -317,6 +331,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { D->getAccess() == AS_none && !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && + !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclRecordAbbrev(); @@ -349,7 +364,6 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { VisitRedeclarable(D); VisitDeclaratorDecl(D); - Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Record.push_back(D->getIdentifierNamespace()); @@ -663,12 +677,17 @@ void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { VisitDeclaratorDecl(D); Record.push_back(D->isMutable()); - if (D->InitializerOrBitWidth.getInt() != ICIS_NoInit || - D->InitializerOrBitWidth.getPointer()) { - Record.push_back(D->InitializerOrBitWidth.getInt() + 1); - Writer.AddStmt(D->InitializerOrBitWidth.getPointer()); - } else { + if (D->InitStorage.getInt() == FieldDecl::ISK_BitWidthOrNothing && + D->InitStorage.getPointer() == nullptr) { Record.push_back(0); + } else if (D->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) { + Record.push_back(D->InitStorage.getInt() + 1); + Writer.AddTypeRef( + QualType(static_cast<Type *>(D->InitStorage.getPointer()), 0), + Record); + } else { + Record.push_back(D->InitStorage.getInt() + 1); + Writer.AddStmt(static_cast<Expr *>(D->InitStorage.getPointer())); } if (!D->getDeclName()) Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record); @@ -753,6 +772,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isTopLevelDeclInObjCContainer() && D->getAccess() == AS_none && !D->isModulePrivate() && + !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier && !D->hasExtInfo() && D->getFirstDecl() == D->getMostRecentDecl() && @@ -930,6 +950,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { } void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + VisitRedeclarable(D); VisitNamedDecl(D); Writer.AddSourceLocation(D->getNamespaceLoc(), Record); Writer.AddSourceLocation(D->getTargetNameLoc(), Record); @@ -1027,6 +1048,17 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { // We only need to record overridden methods once for the canonical decl. Record.push_back(0); } + + if (D->getFirstDecl() == D->getMostRecentDecl() && + !D->isInvalidDecl() && + !D->hasAttrs() && + !D->isTopLevelDeclInObjCContainer() && + D->getDeclName().getNameKind() == DeclarationName::Identifier && + !D->hasExtInfo() && + !D->hasInheritedPrototype() && + D->hasWrittenPrototype()) + AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); + Code = serialization::DECL_CXX_METHOD; } @@ -1449,7 +1481,7 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { // ASTWriter Implementation //===----------------------------------------------------------------------===// -void ASTWriter::WriteDeclsBlockAbbrevs() { +void ASTWriter::WriteDeclAbbrevs() { using namespace llvm; BitCodeAbbrev *Abv; @@ -1552,8 +1584,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl + Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind // EnumDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddTypeRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IntegerType @@ -1600,8 +1631,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl + Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind // RecordDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FlexibleArrayMember Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion @@ -1676,10 +1706,10 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isUsed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl @@ -1738,6 +1768,63 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclVarAbbrev = Stream.EmitAbbrev(Abv); + // Abbreviation for DECL_CXX_METHOD + Abv = new BitCodeAbbrev(); + Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); + // RedeclarableDecl + Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl + // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext + Abv->Add(BitCodeAbbrevOp(0)); // Invalid + Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Implicit + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Used + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Referenced + Abv->Add(BitCodeAbbrevOp(0)); // InObjCContainer + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Access + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID + // NamedDecl + Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier + // ValueDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // DeclaratorDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart + Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo + // FunctionDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure + Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto + Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // DeletedAsWritten + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind + // This Array slurps the rest of the record. Fortunately we want to encode + // (nearly) all the remaining (variable number of) fields in the same way. + // + // This is the function template information if any, then + // NumParams and Params[] from FunctionDecl, and + // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. + // + // Add an AbbrevOp for 'size then elements' and use it here. + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + DeclCXXMethodAbbrev = Stream.EmitAbbrev(Abv); + // Abbreviation for EXPR_DECL_REF Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); @@ -1755,7 +1842,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //RefersToEnclosingLocal + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 1)); // RefersToEnclosingVariableOrCapture Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(Abv); @@ -1796,6 +1884,24 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getKind CharacterLiteralAbbrev = Stream.EmitAbbrev(Abv); + // Abbreviation for EXPR_IMPLICIT_CAST + Abv = new BitCodeAbbrev(); + Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST)); + // Stmt + // Expr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind + // CastExpr + Abv->Add(BitCodeAbbrevOp(0)); // PathSize + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind + // ImplicitCastExpr + ExprImplicitCastAbbrev = Stream.EmitAbbrev(Abv); + Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index a43b3527a7114..e980ce783f5ea 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -307,7 +307,7 @@ void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { // Captures for (const auto &I : S->captures()) { - if (I.capturesThis()) + if (I.capturesThis() || I.capturesVariableArrayType()) Writer.AddDeclRef(nullptr, Record); else Writer.AddDeclRef(I.getCapturedVar(), Record); @@ -333,6 +333,7 @@ void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { VisitExpr(E); Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->getIdentType()); // FIXME: stable encoding + Writer.AddStmt(E->getFunctionName()); Code = serialization::EXPR_PREDEFINED; } @@ -343,7 +344,7 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { Record.push_back(E->getDecl() != E->getFoundDecl()); Record.push_back(E->hasTemplateKWAndArgsInfo()); Record.push_back(E->hadMultipleCandidates()); - Record.push_back(E->refersToEnclosingLocal()); + Record.push_back(E->refersToEnclosingVariableOrCapture()); if (E->hasTemplateKWAndArgsInfo()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -635,6 +636,10 @@ ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); + + if (E->path_size() == 0) + AbbrevToUse = Writer.getExprImplicitCastAbbrev(); + Code = serialization::EXPR_IMPLICIT_CAST; } @@ -1574,6 +1579,17 @@ void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { Code = serialization::EXPR_MATERIALIZE_TEMPORARY; } +void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) { + VisitExpr(E); + Writer.AddSourceLocation(E->LParenLoc, Record); + Writer.AddSourceLocation(E->EllipsisLoc, Record); + Writer.AddSourceLocation(E->RParenLoc, Record); + Writer.AddStmt(E->SubExprs[0]); + Writer.AddStmt(E->SubExprs[1]); + Record.push_back(E->Opcode); + Code = serialization::EXPR_CXX_FOLD; +} + void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); Writer.AddStmt(E->getSourceExpr()); @@ -1581,6 +1597,12 @@ void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { Code = serialization::EXPR_OPAQUE_VALUE; } +void ASTStmtWriter::VisitTypoExpr(TypoExpr *E) { + VisitExpr(E); + // TODO: Figure out sane writer behavior for a TypoExpr, if necessary + assert(false && "Cannot write TypoExpr nodes"); +} + //===----------------------------------------------------------------------===// // CUDA Expressions and Statements. //===----------------------------------------------------------------------===// @@ -1735,18 +1757,39 @@ void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {} void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {} +void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {} + +void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {} + +void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {} + +void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {} + +void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {} + void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); - for (auto *VE : C->varlists()) + for (auto *VE : C->varlists()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->private_copies()) { Writer->Writer.AddStmt(VE); + } } void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); - for (auto *VE : C->varlists()) + for (auto *VE : C->varlists()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->private_copies()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->inits()) { Writer->Writer.AddStmt(VE); + } } void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) { @@ -1826,29 +1869,61 @@ void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) { Writer.AddStmt(E->getAssociatedStmt()); } -void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { +void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); + Record.push_back(D->getCollapsedNumber()); VisitOMPExecutableDirective(D); - Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; + Writer.AddStmt(D->getIterationVariable()); + Writer.AddStmt(D->getLastIteration()); + Writer.AddStmt(D->getCalcLastIteration()); + Writer.AddStmt(D->getPreCond()); + Writer.AddStmt(D->getCond(/* SeparateIter */ false)); + Writer.AddStmt(D->getCond(/* SeparateIter */ true)); + Writer.AddStmt(D->getInit()); + Writer.AddStmt(D->getInc()); + if (isOpenMPWorksharingDirective(D->getDirectiveKind())) { + Writer.AddStmt(D->getIsLastIterVariable()); + Writer.AddStmt(D->getLowerBoundVariable()); + Writer.AddStmt(D->getUpperBoundVariable()); + Writer.AddStmt(D->getStrideVariable()); + Writer.AddStmt(D->getEnsureUpperBound()); + Writer.AddStmt(D->getNextLowerBound()); + Writer.AddStmt(D->getNextUpperBound()); + } + for (auto I : D->counters()) { + Writer.AddStmt(I); + } + for (auto I : D->updates()) { + Writer.AddStmt(I); + } + for (auto I : D->finals()) { + Writer.AddStmt(I); + } } -void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) { +void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); - Record.push_back(D->getCollapsedNumber()); VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) { + VisitOMPLoopDirective(D); Code = serialization::STMT_OMP_SIMD_DIRECTIVE; } void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - Record.push_back(D->getCollapsedNumber()); - VisitOMPExecutableDirective(D); + VisitOMPLoopDirective(D); Code = serialization::STMT_OMP_FOR_DIRECTIVE; } +void ASTStmtWriter::VisitOMPForSimdDirective(OMPForSimdDirective *D) { + VisitOMPLoopDirective(D); + Code = serialization::STMT_OMP_FOR_SIMD_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); @@ -1883,13 +1958,16 @@ void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) { } void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) { - VisitStmt(D); - Record.push_back(D->getNumClauses()); - Record.push_back(D->getCollapsedNumber()); - VisitOMPExecutableDirective(D); + VisitOMPLoopDirective(D); Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE; } +void ASTStmtWriter::VisitOMPParallelForSimdDirective( + OMPParallelForSimdDirective *D) { + VisitOMPLoopDirective(D); + Code = serialization::STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *D) { VisitStmt(D); @@ -1905,6 +1983,23 @@ void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) { Code = serialization::STMT_OMP_TASK_DIRECTIVE; } +void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Writer.AddStmt(D->getX()); + Writer.AddStmt(D->getV()); + Writer.AddStmt(D->getExpr()); + Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPTargetDirective(OMPTargetDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TARGET_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); @@ -1930,6 +2025,19 @@ void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) { Code = serialization::STMT_OMP_FLUSH_DIRECTIVE; } +void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_ORDERED_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPTeamsDirective(OMPTeamsDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TEAMS_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp index 9858122325053..4791388045472 100644 --- a/lib/Serialization/GlobalModuleIndex.cpp +++ b/lib/Serialization/GlobalModuleIndex.cpp @@ -122,11 +122,10 @@ typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> } -GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer, +GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer, llvm::BitstreamCursor Cursor) - : Buffer(Buffer), IdentifierIndex(), - NumIdentifierLookups(), NumIdentifierLookupHits() -{ + : Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(), + NumIdentifierLookupHits() { // Read the global index. bool InGlobalIndexBlock = false; bool Done = false; @@ -260,7 +259,7 @@ GlobalModuleIndex::readIndex(StringRef Path) { return std::make_pair(nullptr, EC_IOError); } - return std::make_pair(new GlobalModuleIndex(Buffer.release(), Cursor), + return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), EC_None); } @@ -494,19 +493,17 @@ namespace { bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Open the module file. - std::unique_ptr<llvm::MemoryBuffer> Buffer; - std::string ErrorStr; - Buffer.reset(FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)); + + auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true); if (!Buffer) { return true; } // Initialize the input stream llvm::BitstreamReader InStreamFile; - llvm::BitstreamCursor InStream; - InStreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - InStream.init(InStreamFile); + InStreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(), + (const unsigned char *)(*Buffer)->getBufferEnd()); + llvm::BitstreamCursor InStream(InStreamFile); // Sniff for the signature. if (InStream.Read(8) != 'C' || @@ -591,6 +588,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { off_t StoredSize = (off_t)Record[Idx++]; time_t StoredModTime = (time_t)Record[Idx++]; + // Skip the stored signature. + // FIXME: we could read the signature out of the import and validate it. + Idx++; + // Retrieve the imported file name. unsigned Length = Record[Idx++]; SmallString<128> ImportedFile(Record.begin() + Idx, diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp index 6f2a3c2204307..6c48a41187c20 100644 --- a/lib/Serialization/Module.cpp +++ b/lib/Serialization/Module.cpp @@ -21,7 +21,7 @@ using namespace serialization; using namespace reader; ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) - : Kind(Kind), File(nullptr), DirectlyImported(false), + : Kind(Kind), File(nullptr), Signature(0), DirectlyImported(false), Generation(Generation), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0), SLocEntryBaseOffset(0), SLocEntryOffsets(nullptr), diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp index 2c10c119a07bd..ac98ca0b87203 100644 --- a/lib/Serialization/ModuleManager.cpp +++ b/lib/Serialization/ModuleManager.cpp @@ -45,10 +45,11 @@ ModuleFile *ModuleManager::lookup(const FileEntry *File) { return Known->second; } -llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { +std::unique_ptr<llvm::MemoryBuffer> +ModuleManager::lookupBuffer(StringRef Name) { const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, /*cacheFailure=*/false); - return InMemoryBuffers[Entry]; + return std::move(InMemoryBuffers[Entry]); } ModuleManager::AddModuleResult @@ -56,6 +57,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, SourceLocation ImportLoc, ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, + ASTFileSignature ExpectedSignature, + std::function<ASTFileSignature(llvm::BitstreamReader &)> + ReadSignature, ModuleFile *&Module, std::string &ErrorStr) { Module = nullptr; @@ -63,6 +67,13 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // Look for the file entry. This only fails if the expected size or // modification time differ. const FileEntry *Entry; + if (Type == MK_ExplicitModule) { + // If we're not expecting to pull this file out of the module cache, it + // might have a different mtime due to being moved across filesystems in + // a distributed build. The size must still match, though. (As must the + // contents, but we can't check that.) + ExpectedModTime = 0; + } if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) { ErrorStr = "module file out of date"; return OutOfDate; @@ -88,7 +99,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, ModuleEntry = New; New->InputFilesValidationTimestamp = 0; - if (New->Kind == MK_Module) { + if (New->Kind == MK_ImplicitModule) { std::string TimestampFilename = New->getTimestampFilename(); vfs::Status Status; // A cached stat value would be fine as well. @@ -98,39 +109,59 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, } // Load the contents of the module - if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { + if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) { // The buffer was already provided for us. - assert(Buffer && "Passed null buffer"); - New->Buffer.reset(Buffer); + New->Buffer = std::move(Buffer); } else { // Open the AST file. - std::error_code ec; + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf( + (std::error_code())); if (FileName == "-") { - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf = - llvm::MemoryBuffer::getSTDIN(); - ec = Buf.getError(); - if (ec) - ErrorStr = ec.message(); - else - New->Buffer = std::move(Buf.get()); + Buf = llvm::MemoryBuffer::getSTDIN(); } else { // Leave the FileEntry open so if it gets read again by another // ModuleManager it must be the same underlying file. // FIXME: Because FileManager::getFile() doesn't guarantee that it will // give us an open file, this may not be 100% reliable. - New->Buffer.reset(FileMgr.getBufferForFile(New->File, &ErrorStr, - /*IsVolatile*/false, - /*ShouldClose*/false)); + Buf = FileMgr.getBufferForFile(New->File, + /*IsVolatile=*/false, + /*ShouldClose=*/false); } - - if (!New->Buffer) + + if (!Buf) { + ErrorStr = Buf.getError().message(); return Missing; + } + + New->Buffer = std::move(*Buf); } // Initialize the stream New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), (const unsigned char *)New->Buffer->getBufferEnd()); } + + if (ExpectedSignature) { + if (NewModule) + ModuleEntry->Signature = ReadSignature(ModuleEntry->StreamFile); + else + assert(ModuleEntry->Signature == ReadSignature(ModuleEntry->StreamFile)); + + if (ModuleEntry->Signature != ExpectedSignature) { + ErrorStr = ModuleEntry->Signature ? "signature mismatch" + : "could not read module signature"; + + if (NewModule) { + // Remove the module file immediately, since removeModules might try to + // invalidate the file cache for Entry, and that is not safe if this + // module is *itself* up to date, but has an out-of-date importer. + Modules.erase(Entry); + Chain.pop_back(); + delete ModuleEntry; + } + return OutOfDate; + } + } if (ImportedBy) { ModuleEntry->ImportedBy.insert(ImportedBy); @@ -187,12 +218,13 @@ void ModuleManager::removeModules( Chain.erase(first, last); } -void ModuleManager::addInMemoryBuffer(StringRef FileName, - llvm::MemoryBuffer *Buffer) { - - const FileEntry *Entry = FileMgr.getVirtualFile(FileName, - Buffer->getBufferSize(), 0); - InMemoryBuffers[Entry] = Buffer; +void +ModuleManager::addInMemoryBuffer(StringRef FileName, + std::unique_ptr<llvm::MemoryBuffer> Buffer) { + + const FileEntry *Entry = + FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0); + InMemoryBuffers[Entry] = std::move(Buffer); } ModuleManager::VisitState *ModuleManager::allocateVisitState() { @@ -249,7 +281,7 @@ ModuleManager::~ModuleManager() { void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData, - llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit) { + llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) { // If the visitation order vector is the wrong size, recompute the order. if (VisitOrder.size() != Chain.size()) { unsigned N = size(); |