diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization')
13 files changed, 3563 insertions, 1613 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp index a817687..ad046ff 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp @@ -95,21 +95,21 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { case Decl::TranslationUnit: case Decl::Namespace: case Decl::LinkageSpec: - return 0; + return nullptr; // C/C++ tag types can only be defined in one place. case Decl::Enum: case Decl::Record: if (const TagDecl *Def = cast<TagDecl>(DC)->getDefinition()) return Def; - return 0; + return nullptr; // FIXME: These can be defined in one place... except special member // functions and out-of-line definitions. case Decl::CXXRecord: case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: - return 0; + return nullptr; // Each function, method, and block declaration is its own DeclContext. case Decl::Function: @@ -131,14 +131,14 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { if (const ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(DC)->getDefinition()) return Def; - return 0; + return nullptr; // FIXME: These are defined in one place, but properties in class extensions // end up being back-patched into the main interface. See // Sema::HandlePropertyInClassExtension for the offending code. case Decl::ObjCInterface: - return 0; - + return nullptr; + default: llvm_unreachable("Unhandled DeclContext in AST reader"); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h index ef81e69..c766974 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h @@ -26,8 +26,13 @@ enum DeclUpdateKind { UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, 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_DECL_MARKED_USED, + UPD_MANGLING_NUMBER, + UPD_STATIC_LOCAL_NUMBER }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index 4d1b4b9..ae41654 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -22,6 +22,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" @@ -29,6 +30,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Basic/VersionTuple.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" @@ -49,16 +51,100 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" -#include "llvm/Support/system_error.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstdio> #include <iterator> +#include <system_error> using namespace clang; using namespace clang::serialization; using namespace clang::serialization::reader; using llvm::BitstreamCursor; + +//===----------------------------------------------------------------------===// +// ChainedASTReaderListener implementation +//===----------------------------------------------------------------------===// + +bool +ChainedASTReaderListener::ReadFullVersionInformation(StringRef FullVersion) { + return First->ReadFullVersionInformation(FullVersion) || + Second->ReadFullVersionInformation(FullVersion); +} +void ChainedASTReaderListener::ReadModuleName(StringRef ModuleName) { + First->ReadModuleName(ModuleName); + Second->ReadModuleName(ModuleName); +} +void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) { + First->ReadModuleMapFile(ModuleMapPath); + Second->ReadModuleMapFile(ModuleMapPath); +} +bool ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) { + return First->ReadLanguageOptions(LangOpts, Complain) || + Second->ReadLanguageOptions(LangOpts, Complain); +} +bool +ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) { + return First->ReadTargetOptions(TargetOpts, Complain) || + Second->ReadTargetOptions(TargetOpts, Complain); +} +bool ChainedASTReaderListener::ReadDiagnosticOptions( + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { + return First->ReadDiagnosticOptions(DiagOpts, Complain) || + Second->ReadDiagnosticOptions(DiagOpts, Complain); +} +bool +ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts, + bool Complain) { + return First->ReadFileSystemOptions(FSOpts, Complain) || + Second->ReadFileSystemOptions(FSOpts, Complain); +} + +bool ChainedASTReaderListener::ReadHeaderSearchOptions( + const HeaderSearchOptions &HSOpts, bool Complain) { + return First->ReadHeaderSearchOptions(HSOpts, Complain) || + Second->ReadHeaderSearchOptions(HSOpts, Complain); +} +bool ChainedASTReaderListener::ReadPreprocessorOptions( + const PreprocessorOptions &PPOpts, bool Complain, + std::string &SuggestedPredefines) { + return First->ReadPreprocessorOptions(PPOpts, Complain, + SuggestedPredefines) || + Second->ReadPreprocessorOptions(PPOpts, Complain, SuggestedPredefines); +} +void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M, + unsigned Value) { + First->ReadCounter(M, Value); + Second->ReadCounter(M, Value); +} +bool ChainedASTReaderListener::needsInputFileVisitation() { + return First->needsInputFileVisitation() || + Second->needsInputFileVisitation(); +} +bool ChainedASTReaderListener::needsSystemInputFileVisitation() { + return First->needsSystemInputFileVisitation() || + Second->needsSystemInputFileVisitation(); +} +void ChainedASTReaderListener::visitModuleFile(StringRef Filename) { + First->visitModuleFile(Filename); + Second->visitModuleFile(Filename); +} +bool ChainedASTReaderListener::visitInputFile(StringRef Filename, + bool isSystem, + bool isOverridden) { + bool Continue = false; + if (First->needsInputFileVisitation() && + (!isSystem || First->needsSystemInputFileVisitation())) + Continue |= First->visitInputFile(Filename, isSystem, isOverridden); + if (Second->needsInputFileVisitation() && + (!isSystem || Second->needsSystemInputFileVisitation())) + Continue |= Second->visitInputFile(Filename, isSystem, isOverridden); + return Continue; +} + //===----------------------------------------------------------------------===// // PCH validator implementation //===----------------------------------------------------------------------===// @@ -140,8 +226,6 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts, CHECK_TARGET_OPT(Triple, "target"); CHECK_TARGET_OPT(CPU, "target CPU"); CHECK_TARGET_OPT(ABI, "target ABI"); - CHECK_TARGET_OPT(CXXABI, "target C++ ABI"); - CHECK_TARGET_OPT(LinkerVersion, "target linker version"); #undef CHECK_TARGET_OPT // Compare feature sets. @@ -197,14 +281,14 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts, bool Complain) { const LangOptions &ExistingLangOpts = PP.getLangOpts(); return checkLanguageOptions(LangOpts, ExistingLangOpts, - Complain? &Reader.Diags : 0); + Complain? &Reader.Diags : nullptr); } bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain) { const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts(); return checkTargetOptions(TargetOpts, ExistingTargetOpts, - Complain? &Reader.Diags : 0); + Complain? &Reader.Diags : nullptr); } namespace { @@ -214,11 +298,124 @@ namespace { DeclsMap; } +static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags, + DiagnosticsEngine &Diags, + bool Complain) { + typedef DiagnosticsEngine::Level Level; + + // Check current mappings for new -Werror mappings, and the stored mappings + // for cases that were explicitly mapped to *not* be errors that are now + // errors because of options like -Werror. + DiagnosticsEngine *MappingSources[] = { &Diags, &StoredDiags }; + + for (DiagnosticsEngine *MappingSource : MappingSources) { + for (auto DiagIDMappingPair : MappingSource->getDiagnosticMappings()) { + diag::kind DiagID = DiagIDMappingPair.first; + Level CurLevel = Diags.getDiagnosticLevel(DiagID, SourceLocation()); + if (CurLevel < DiagnosticsEngine::Error) + continue; // not significant + Level StoredLevel = + StoredDiags.getDiagnosticLevel(DiagID, SourceLocation()); + if (StoredLevel < DiagnosticsEngine::Error) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror=" + + Diags.getDiagnosticIDs()->getWarningOptionForDiag(DiagID).str(); + return true; + } + } + } + + return false; +} + +static bool isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) { + diag::Severity Ext = Diags.getExtensionHandlingBehavior(); + if (Ext == diag::Severity::Warning && Diags.getWarningsAsErrors()) + return true; + return Ext >= diag::Severity::Error; +} + +static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags, + DiagnosticsEngine &Diags, + bool IsSystem, bool Complain) { + // Top-level options + if (IsSystem) { + if (Diags.getSuppressSystemWarnings()) + return false; + // If -Wsystem-headers was not enabled before, be conservative + if (StoredDiags.getSuppressSystemWarnings()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Wsystem-headers"; + return true; + } + } + + if (Diags.getWarningsAsErrors() && !StoredDiags.getWarningsAsErrors()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror"; + return true; + } + + if (Diags.getWarningsAsErrors() && Diags.getEnableAllWarnings() && + !StoredDiags.getEnableAllWarnings()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Weverything -Werror"; + return true; + } + + if (isExtHandlingFromDiagsError(Diags) && + !isExtHandlingFromDiagsError(StoredDiags)) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-pedantic-errors"; + return true; + } + + return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain); +} + +bool PCHValidator::ReadDiagnosticOptions( + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { + DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); + IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs()); + IntrusiveRefCntPtr<DiagnosticsEngine> Diags( + new DiagnosticsEngine(DiagIDs, DiagOpts.get())); + // This should never fail, because we would have processed these options + // before writing them to an ASTFile. + ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false); + + ModuleManager &ModuleMgr = Reader.getModuleManager(); + assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); + + // If the original import came from a file explicitly generated by the user, + // don't check the diagnostic mappings. + // FIXME: currently this is approximated by checking whether this is not a + // module import. + // Note: ModuleMgr.rbegin() may not be the current module, but it must be in + // the transitive closure of its imports, since unrelated modules cannot be + // imported until after this module finishes validation. + ModuleFile *TopImport = *ModuleMgr.rbegin(); + while (!TopImport->ImportedBy.empty()) + TopImport = TopImport->ImportedBy[0]; + if (TopImport->Kind != MK_Module) + return false; + + StringRef ModuleName = TopImport->ModuleName; + assert(!ModuleName.empty() && "diagnostic options read before module name"); + + Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName); + assert(M && "missing module"); + + // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that + // contains the union of their flags. + return checkDiagnosticMappings(*Diags, ExistingDiags, M->IsSystem, Complain); +} + /// \brief Collect the macro definitions provided by the given preprocessor /// options. -static void collectMacroDefinitions(const PreprocessorOptions &PPOpts, - MacroDefinitionsMap &Macros, - SmallVectorImpl<StringRef> *MacroNames = 0){ +static void +collectMacroDefinitions(const PreprocessorOptions &PPOpts, + MacroDefinitionsMap &Macros, + SmallVectorImpl<StringRef> *MacroNames = nullptr) { for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) { StringRef Macro = PPOpts.Macros[I].first; bool IsUndef = PPOpts.Macros[I].second; @@ -373,7 +570,7 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts(); return checkPreprocessorOptions(PPOpts, ExistingPPOpts, - Complain? &Reader.Diags : 0, + Complain? &Reader.Diags : nullptr, PP.getFileManager(), SuggestedPredefines, PP.getLangOpts()); @@ -387,9 +584,10 @@ void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { // AST reader implementation //===----------------------------------------------------------------------===// -void -ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) { +void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener, + bool TakeOwnership) { DeserializationListener = Listener; + OwnsDeserializationListener = TakeOwnership; } @@ -401,19 +599,19 @@ unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { std::pair<unsigned, unsigned> ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } ASTSelectorLookupTrait::internal_key_type ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; + using namespace llvm::support; SelectorTable &SelTable = Reader.getContext().Selectors; - unsigned N = ReadUnalignedLE16(d); - IdentifierInfo *FirstII - = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); + unsigned N = endian::readNext<uint16_t, little, unaligned>(d); + IdentifierInfo *FirstII = Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d)); if (N == 0) return SelTable.getNullarySelector(FirstII); else if (N == 1) @@ -422,7 +620,8 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { SmallVector<IdentifierInfo *, 16> Args; Args.push_back(FirstII); for (unsigned I = 1; I != N; ++I) - Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d))); + Args.push_back(Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d))); return SelTable.getSelector(N, Args.data()); } @@ -430,13 +629,16 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { ASTSelectorLookupTrait::data_type ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; + using namespace llvm::support; data_type Result; - Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d)); - unsigned NumInstanceMethodsAndBits = ReadUnalignedLE16(d); - unsigned NumFactoryMethodsAndBits = ReadUnalignedLE16(d); + Result.ID = Reader.getGlobalSelectorID( + F, endian::readNext<uint32_t, little, unaligned>(d)); + unsigned NumInstanceMethodsAndBits = + endian::readNext<uint16_t, little, unaligned>(d); + unsigned NumFactoryMethodsAndBits = + endian::readNext<uint16_t, little, unaligned>(d); Result.InstanceBits = NumInstanceMethodsAndBits & 0x3; Result.FactoryBits = NumFactoryMethodsAndBits & 0x3; unsigned NumInstanceMethods = NumInstanceMethodsAndBits >> 2; @@ -444,15 +646,15 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, // Load instance methods for (unsigned I = 0; I != NumInstanceMethods; ++I) { - if (ObjCMethodDecl *Method - = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) + if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( + F, endian::readNext<uint32_t, little, unaligned>(d))) Result.Instance.push_back(Method); } // Load factory methods for (unsigned I = 0; I != NumFactoryMethods; ++I) { - if (ObjCMethodDecl *Method - = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) + if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( + F, endian::readNext<uint32_t, little, unaligned>(d))) Result.Factory.push_back(Method); } @@ -465,9 +667,9 @@ unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) { std::pair<unsigned, unsigned> ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned DataLen = ReadUnalignedLE16(d); - unsigned KeyLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } @@ -490,8 +692,8 @@ static bool isInterestingIdentifier(IdentifierInfo &II) { IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - unsigned RawID = ReadUnalignedLE32(d); + using namespace llvm::support; + unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); bool IsInteresting = RawID & 0x01; // Wipe out the "is interesting" bit. @@ -517,8 +719,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, return II; } - unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d); - unsigned Bits = ReadUnalignedLE16(d); + unsigned ObjCOrBuiltinID = endian::readNext<uint16_t, little, unaligned>(d); + unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d); bool CPlusPlusOperatorKeyword = Bits & 0x01; Bits >>= 1; bool HasRevertedTokenIDToIdentifier = Bits & 0x01; @@ -567,11 +769,13 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // If this identifier is a macro, deserialize the macro // definition. if (hadMacroDefinition) { - uint32_t MacroDirectivesOffset = ReadUnalignedLE32(d); + uint32_t MacroDirectivesOffset = + endian::readNext<uint32_t, little, unaligned>(d); DataLen -= 4; SmallVector<uint32_t, 8> LocalMacroIDs; if (hasSubmoduleMacros) { - while (uint32_t LocalMacroID = ReadUnalignedLE32(d)) { + while (uint32_t LocalMacroID = + endian::readNext<uint32_t, little, unaligned>(d)) { DataLen -= 4; LocalMacroIDs.push_back(LocalMacroID); } @@ -579,11 +783,34 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, } if (F.Kind == MK_Module) { + // Macro definitions are stored from newest to oldest, so reverse them + // before registering them. + llvm::SmallVector<unsigned, 8> MacroSizes; for (SmallVectorImpl<uint32_t>::iterator - I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; ++I) { - MacroID MacID = Reader.getGlobalMacroID(F, *I); - Reader.addPendingMacroFromModule(II, &F, MacID, F.DirectImportLoc); + I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) { + unsigned Size = 1; + + static const uint32_t HasOverridesFlag = 0x80000000U; + if (I + 1 != E && (I[1] & HasOverridesFlag)) + Size += 1 + (I[1] & ~HasOverridesFlag); + + MacroSizes.push_back(Size); + I += Size; + } + + SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end(); + for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(), + SE = MacroSizes.rend(); + SI != SE; ++SI) { + I -= *SI; + + uint32_t LocalMacroID = *I; + ArrayRef<uint32_t> Overrides; + if (*SI != 1) + Overrides = llvm::makeArrayRef(&I[2], *SI - 2); + Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides); } + assert(I == LocalMacroIDs.begin()); } else { Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset); } @@ -596,7 +823,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, if (DataLen > 0) { SmallVector<uint32_t, 4> DeclIDs; for (; DataLen > 0; DataLen -= 4) - DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d))); + DeclIDs.push_back(Reader.getGlobalDeclID( + F, endian::readNext<uint32_t, little, unaligned>(d))); Reader.SetGloballyVisibleDecls(II, DeclIDs); } @@ -664,34 +892,37 @@ ASTDeclContextNameLookupTrait::GetInternalKey( std::pair<unsigned, unsigned> ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } ASTDeclContextNameLookupTrait::internal_key_type ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; + using namespace llvm::support; DeclNameKey Key; Key.Kind = (DeclarationName::NameKind)*d++; switch (Key.Kind) { case DeclarationName::Identifier: - Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); + Key.Data = (uint64_t)Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d)); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: Key.Data = - (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d)) - .getAsOpaquePtr(); + (uint64_t)Reader.getLocalSelector( + F, endian::readNext<uint32_t, little, unaligned>( + d)).getAsOpaquePtr(); break; case DeclarationName::CXXOperatorName: Key.Data = *d++; // OverloadedOperatorKind break; case DeclarationName::CXXLiteralOperatorName: - Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); + Key.Data = (uint64_t)Reader.getLocalIdentifier( + F, endian::readNext<uint32_t, little, unaligned>(d)); break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: @@ -708,8 +939,8 @@ ASTDeclContextNameLookupTrait::data_type ASTDeclContextNameLookupTrait::ReadData(internal_key_type, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - unsigned NumDecls = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned NumDecls = endian::readNext<uint16_t, little, unaligned>(d); LE32DeclID *Start = reinterpret_cast<LE32DeclID *>( const_cast<unsigned char *>(d)); return std::make_pair(Start, Start + NumDecls); @@ -749,11 +980,11 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M, Error("Expected visible lookup table block"); return true; } - Info.NameLookupTableData - = ASTDeclContextNameLookupTable::Create( - (const unsigned char *)Blob.data() + Record[0], - (const unsigned char *)Blob.data(), - ASTDeclContextNameLookupTrait(*this, M)); + Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create( + (const unsigned char *)Blob.data() + Record[0], + (const unsigned char *)Blob.data() + sizeof(uint32_t), + (const unsigned char *)Blob.data(), + ASTDeclContextNameLookupTrait(*this, M)); } return false; @@ -1023,8 +1254,8 @@ bool ASTReader::ReadSLocEntry(int ID) { llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name); - SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID, - BaseOffset + Offset, IncludeLoc); + SourceMgr.createFileID(Buffer, FileCharacter, ID, BaseOffset + Offset, + IncludeLoc); break; } @@ -1059,7 +1290,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { // FIXME: Can we map this down to a particular submodule? That would be // ideal. - return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName)); + return std::make_pair(M->ImportLoc, StringRef(M->ModuleName)); } /// \brief Find the location where the module F is imported. @@ -1070,14 +1301,10 @@ SourceLocation ASTReader::getImportLocation(ModuleFile *F) { // Otherwise we have a PCH. It's considered to be "imported" at the first // location of its includer. if (F->ImportedBy.empty() || !F->ImportedBy[0]) { - // Main file is the importer. We assume that it is the first entry in the - // entry table. We can't ask the manager, because at the time of PCH loading - // the main file entry doesn't exist yet. - // The very first entry is the invalid instantiation loc, which takes up - // offsets 0 and 1. - return SourceLocation::getFromRawEncoding(2U); - } - //return F->Loaders[0]->FirstLoc; + // Main file is the importer. + assert(!SourceMgr.getMainFileID().isInvalid() && "missing main file"); + return SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); + } return F->ImportedBy[0]->FirstLoc; } @@ -1126,7 +1353,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { Stream.JumpToBit(Offset); RecordData Record; SmallVector<IdentifierInfo*, 16> MacroArgs; - MacroInfo *Macro = 0; + MacroInfo *Macro = nullptr; while (true) { // Advance to the next record, but if we get to the end of the block, don't @@ -1169,6 +1396,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, SubModID); MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex)); MI->setIsUsed(Record[NextIndex++]); + MI->setUsedForHeaderGuard(Record[NextIndex++]); if (RecType == PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. @@ -1214,7 +1442,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { case PP_TOKEN: { // If we see a TOKEN before a PP_MACRO_*, then the file is // erroneous, just pretend we didn't see this. - if (Macro == 0) break; + if (!Macro) break; unsigned Idx = 0; Token Tok = ReadToken(F, Record, Idx); @@ -1262,16 +1490,18 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) { std::pair<unsigned, unsigned> HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) { - unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = (unsigned) endian::readNext<uint16_t, little, unaligned>(d); unsigned DataLen = (unsigned) *d++; return std::make_pair(KeyLen, DataLen); } HeaderFileInfoTrait::internal_key_type HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { + using namespace llvm::support; internal_key_type ikey; - ikey.Size = off_t(clang::io::ReadUnalignedLE64(d)); - ikey.ModTime = time_t(clang::io::ReadUnalignedLE64(d)); + ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d)); + ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d)); ikey.Filename = (const char *)d; return ikey; } @@ -1280,7 +1510,7 @@ HeaderFileInfoTrait::data_type HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, unsigned DataLen) { const unsigned char *End = d + DataLen; - using namespace clang::io; + using namespace llvm::support; HeaderFileInfo HFI; unsigned Flags = *d++; HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole> @@ -1290,10 +1520,11 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, HFI.DirInfo = (Flags >> 2) & 0x03; HFI.Resolved = (Flags >> 1) & 0x01; HFI.IndexHeaderMapHeader = Flags & 0x01; - HFI.NumIncludes = ReadUnalignedLE16(d); - HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M, - ReadUnalignedLE32(d)); - if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) { + HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d); + HFI.ControllingMacroID = Reader.getGlobalIdentifierID( + M, endian::readNext<uint32_t, little, unaligned>(d)); + if (unsigned FrameworkOffset = + endian::readNext<uint32_t, little, unaligned>(d)) { // The framework offset is 1 greater than the actual offset, // since 0 is used as an indicator for "no framework name". StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1); @@ -1301,7 +1532,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, } if (d != End) { - uint32_t LocalSMID = ReadUnalignedLE32(d); + uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d); if (LocalSMID) { // This header is part of a module. Associate it with the module to enable // implicit module import. @@ -1323,12 +1554,19 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, return HFI; } -void ASTReader::addPendingMacroFromModule(IdentifierInfo *II, - ModuleFile *M, - GlobalMacroID GMacID, - SourceLocation ImportLoc) { +void +ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M, + GlobalMacroID GMacID, + ArrayRef<SubmoduleID> Overrides) { assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); - PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, ImportLoc)); + SubmoduleID *OverrideData = nullptr; + if (!Overrides.empty()) { + OverrideData = new (Context) SubmoduleID[Overrides.size() + 1]; + OverrideData[0] = Overrides.size(); + for (unsigned I = 0; I != Overrides.size(); ++I) + OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]); + } + PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData)); } void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II, @@ -1452,7 +1690,7 @@ void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { // If there is a global index, look there first to determine which modules // provably do not have any results for this identifier. GlobalModuleIndex::HitSet Hits; - GlobalModuleIndex::HitSet *HitsPtr = 0; + GlobalModuleIndex::HitSet *HitsPtr = nullptr; if (!loadGlobalIndex()) { if (GlobalIndex->lookupIdentifier(II.getName(), Hits)) { HitsPtr = &Hits; @@ -1474,7 +1712,60 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { // Update the generation for this identifier. if (getContext().getLangOpts().Modules) - IdentifierGeneration[II] = CurrentGeneration; + IdentifierGeneration[II] = getGeneration(); +} + +struct ASTReader::ModuleMacroInfo { + SubmoduleID SubModID; + MacroInfo *MI; + SubmoduleID *Overrides; + // FIXME: Remove this. + ModuleFile *F; + + bool isDefine() const { return MI; } + + SubmoduleID getSubmoduleID() const { return SubModID; } + + ArrayRef<SubmoduleID> getOverriddenSubmodules() const { + if (!Overrides) + return None; + return llvm::makeArrayRef(Overrides + 1, *Overrides); + } + + DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const { + if (!MI) + return nullptr; + return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true); + } +}; + +ASTReader::ModuleMacroInfo * +ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) { + ModuleMacroInfo Info; + + uint32_t ID = PMInfo.ModuleMacroData.MacID; + if (ID & 1) { + // Macro undefinition. + Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1); + Info.MI = nullptr; + } else { + // Macro definition. + GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1); + assert(GMacID); + + // If this macro has already been loaded, don't do so again. + // FIXME: This is highly dubious. Multiple macro definitions can have the + // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc. + if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS]) + return nullptr; + + Info.MI = getMacro(GMacID); + Info.SubModID = Info.MI->getOwningModuleID(); + } + Info.Overrides = PMInfo.ModuleMacroData.Overrides; + Info.F = PMInfo.M; + + return new (Context) ModuleMacroInfo(Info); } void ASTReader::resolvePendingMacro(IdentifierInfo *II, @@ -1486,42 +1777,21 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, PMInfo.PCHMacroData.MacroDirectivesOffset); return; } - - // Module Macro. - GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID; - SourceLocation ImportLoc = - SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc); + // Module Macro. - assert(GMacID); - // If this macro has already been loaded, don't do so again. - if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS]) + ModuleMacroInfo *MMI = getModuleMacro(PMInfo); + if (!MMI) return; - MacroInfo *MI = getMacro(GMacID); - SubmoduleID SubModID = MI->getOwningModuleID(); - MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc, - /*isImported=*/true); - - // Determine whether this macro definition is visible. - bool Hidden = false; - Module *Owner = 0; - if (SubModID) { - if ((Owner = getSubmodule(SubModID))) { - if (Owner->NameVisibility == Module::Hidden) { - // The owning module is not visible, and this macro definition - // should not be, either. - Hidden = true; - - // Note that this macro definition was hidden because its owning - // module is not yet visible. - HiddenNamesMap[Owner].push_back(HiddenName(II, MD)); - } - } + Module *Owner = getSubmodule(MMI->getSubmoduleID()); + if (Owner && Owner->NameVisibility == Module::Hidden) { + // Macros in the owning module are hidden. Just remember this macro to + // install if we make this module visible. + HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI)); + } else { + installImportedMacro(II, MMI, Owner, /*FromFinalization*/false); } - - if (!Hidden) - installImportedMacro(II, MD, Owner); } void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, @@ -1548,10 +1818,10 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, } // Deserialize the macro directives history in reverse source-order. - MacroDirective *Latest = 0, *Earliest = 0; + MacroDirective *Latest = nullptr, *Earliest = nullptr; unsigned Idx = 0, N = Record.size(); while (Idx < N) { - MacroDirective *MD = 0; + MacroDirective *MD = nullptr; SourceLocation Loc = ReadSourceLocation(M, Record, Idx); MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++]; switch (K) { @@ -1591,7 +1861,7 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, Module *NewOwner, ASTReader &Reader) { assert(PrevMI && NewMI); - Module *PrevOwner = 0; + Module *PrevOwner = nullptr; if (SubmoduleID PrevModID = PrevMI->getOwningModuleID()) PrevOwner = Reader.getSubmodule(PrevModID); SourceManager &SrcMgr = Reader.getSourceManager(); @@ -1606,34 +1876,181 @@ static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, return PrevInSystem && NewInSystem; } -void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD, - Module *Owner) { - assert(II && MD); +void ASTReader::removeOverriddenMacros(IdentifierInfo *II, + AmbiguousMacros &Ambig, + ArrayRef<SubmoduleID> Overrides) { + for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) { + SubmoduleID OwnerID = Overrides[OI]; + + // If this macro is not yet visible, remove it from the hidden names list. + Module *Owner = getSubmodule(OwnerID); + HiddenNames &Hidden = HiddenNamesMap[Owner]; + HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II); + if (HI != Hidden.HiddenMacros.end()) { + auto SubOverrides = HI->second->getOverriddenSubmodules(); + Hidden.HiddenMacros.erase(HI); + removeOverriddenMacros(II, Ambig, SubOverrides); + } + + // If this macro is already in our list of conflicts, remove it from there. + Ambig.erase( + std::remove_if(Ambig.begin(), Ambig.end(), [&](DefMacroDirective *MD) { + return MD->getInfo()->getOwningModuleID() == OwnerID; + }), + Ambig.end()); + } +} - DefMacroDirective *DefMD = cast<DefMacroDirective>(MD); +ASTReader::AmbiguousMacros * +ASTReader::removeOverriddenMacros(IdentifierInfo *II, + ArrayRef<SubmoduleID> Overrides) { MacroDirective *Prev = PP.getMacroDirective(II); - if (Prev) { - MacroDirective::DefInfo PrevDef = Prev->getDefinition(); - MacroInfo *PrevMI = PrevDef.getMacroInfo(); - MacroInfo *NewMI = DefMD->getInfo(); - if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP, - /*Syntactically=*/true)) { - // Before marking the macros as ambiguous, check if this is a case where - // both macros are in system headers. If so, we trust that the system - // did not get it wrong. This also handles cases where Clang's own - // headers have a different spelling of certain system macros: - // #define LONG_MAX __LONG_MAX__ (clang's limits.h) - // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) - if (!areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) { - PrevDef.getDirective()->setAmbiguous(true); - DefMD->setAmbiguous(true); - } + if (!Prev && Overrides.empty()) + return nullptr; + + DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective() + : nullptr; + if (PrevDef && PrevDef->isAmbiguous()) { + // We had a prior ambiguity. Check whether we resolve it (or make it worse). + AmbiguousMacros &Ambig = AmbiguousMacroDefs[II]; + Ambig.push_back(PrevDef); + + removeOverriddenMacros(II, Ambig, Overrides); + + if (!Ambig.empty()) + return &Ambig; + + AmbiguousMacroDefs.erase(II); + } else { + // There's no ambiguity yet. Maybe we're introducing one. + AmbiguousMacros Ambig; + if (PrevDef) + Ambig.push_back(PrevDef); + + removeOverriddenMacros(II, Ambig, Overrides); + + if (!Ambig.empty()) { + AmbiguousMacros &Result = AmbiguousMacroDefs[II]; + std::swap(Result, Ambig); + return &Result; } } - + + // We ended up with no ambiguity. + return nullptr; +} + +void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, + Module *Owner, bool FromFinalization) { + assert(II && Owner); + + SourceLocation ImportLoc = Owner->MacroVisibilityLoc; + if (ImportLoc.isInvalid() && !FromFinalization) { + // FIXME: If we made macros from this module visible but didn't provide a + // source location for the import, we don't have a location for the macro. + // Use the location at which the containing module file was first imported + // for now. + ImportLoc = MMI->F->DirectImportLoc; + assert(ImportLoc.isValid() && "no import location for a visible macro?"); + } + + AmbiguousMacros *Prev = + removeOverriddenMacros(II, MMI->getOverriddenSubmodules()); + + // Create a synthetic macro definition corresponding to the import (or null + // if this was an undefinition of the macro). + DefMacroDirective *MD = MMI->import(PP, ImportLoc); + + // If there's no ambiguity, just install the macro. + if (!Prev) { + if (MD) + PP.appendMacroDirective(II, MD); + else + PP.appendMacroDirective(II, PP.AllocateUndefMacroDirective(ImportLoc)); + return; + } + assert(!Prev->empty()); + + if (!MD) { + // We imported a #undef that didn't remove all prior definitions. The most + // recent prior definition remains, and we install it in the place of the + // imported directive. + MacroInfo *NewMI = Prev->back()->getInfo(); + Prev->pop_back(); + MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc, /*Imported*/true); + } + + // We're introducing a macro definition that creates or adds to an ambiguity. + // We can resolve that ambiguity if this macro is token-for-token identical to + // all of the existing definitions. + MacroInfo *NewMI = MD->getInfo(); + assert(NewMI && "macro definition with no MacroInfo?"); + while (!Prev->empty()) { + MacroInfo *PrevMI = Prev->back()->getInfo(); + assert(PrevMI && "macro definition with no MacroInfo?"); + + // Before marking the macros as ambiguous, check if this is a case where + // both macros are in system headers. If so, we trust that the system + // did not get it wrong. This also handles cases where Clang's own + // headers have a different spelling of certain system macros: + // #define LONG_MAX __LONG_MAX__ (clang's limits.h) + // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) + // + // FIXME: Remove the defined-in-system-headers check. clang's limits.h + // overrides the system limits.h's macros, so there's no conflict here. + if (NewMI != PrevMI && + !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) && + !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) + break; + + // The previous definition is the same as this one (or both are defined in + // system modules so we can assume they're equivalent); we don't need to + // track it any more. + Prev->pop_back(); + } + + if (!Prev->empty()) + MD->setAmbiguous(true); + PP.appendMacroDirective(II, MD); } +ASTReader::InputFileInfo +ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { + // Go find this input file. + BitstreamCursor &Cursor = F.InputFilesCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(F.InputFileOffsets[ID-1]); + + unsigned Code = Cursor.ReadCode(); + RecordData Record; + StringRef Blob; + + unsigned Result = Cursor.readRecord(Code, Record, &Blob); + assert(static_cast<InputFileRecordTypes>(Result) == INPUT_FILE && + "invalid record type for input file"); + (void)Result; + + std::string Filename; + off_t StoredSize; + time_t StoredTime; + bool Overridden; + + assert(Record[0] == ID && "Bogus stored ID or offset"); + StoredSize = static_cast<off_t>(Record[1]); + StoredTime = static_cast<time_t>(Record[2]); + Overridden = static_cast<bool>(Record[3]); + Filename = Blob; + MaybeAddSystemRootToFilename(F, Filename); + + InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden }; + return R; +} + +std::string ASTReader::getInputFileName(ModuleFile &F, unsigned int ID) { + return readInputFileInfo(F, ID).Filename; +} + InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { // If this ID is bogus, just return an empty input file. if (ID == 0 || ID > F.InputFilesLoaded.size()) @@ -1643,107 +2060,113 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { if (F.InputFilesLoaded[ID-1].getFile()) return F.InputFilesLoaded[ID-1]; + if (F.InputFilesLoaded[ID-1].isNotFound()) + return InputFile(); + // Go find this input file. BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(F.InputFileOffsets[ID-1]); - unsigned Code = Cursor.ReadCode(); - RecordData Record; - StringRef Blob; - switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { - case INPUT_FILE: { - unsigned StoredID = Record[0]; - assert(ID == StoredID && "Bogus stored ID or offset"); - (void)StoredID; - off_t StoredSize = (off_t)Record[1]; - time_t StoredTime = (time_t)Record[2]; - bool Overridden = (bool)Record[3]; - - // Get the file entry for this input file. - StringRef OrigFilename = Blob; - std::string Filename = OrigFilename; - MaybeAddSystemRootToFilename(F, Filename); - const FileEntry *File - = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime) - : FileMgr.getFile(Filename, /*OpenFile=*/false); - - // If we didn't find the file, resolve it relative to the - // original directory from which this AST file was created. - if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() && - F.OriginalDir != CurrentDir) { - std::string Resolved = resolveFileRelativeToOriginalDir(Filename, - F.OriginalDir, - CurrentDir); - if (!Resolved.empty()) - File = FileMgr.getFile(Resolved); - } - - // For an overridden file, create a virtual file with the stored - // size/timestamp. - if (Overridden && File == 0) { - File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); - } - - if (File == 0) { - if (Complain) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by AST file"; - Error(ErrorStr.c_str()); - } - return InputFile(); - } + InputFileInfo FI = readInputFileInfo(F, ID); + off_t StoredSize = FI.StoredSize; + time_t StoredTime = FI.StoredTime; + bool Overridden = FI.Overridden; + StringRef Filename = FI.Filename; + + const FileEntry *File + = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime) + : FileMgr.getFile(Filename, /*OpenFile=*/false); + + // If we didn't find the file, resolve it relative to the + // original directory from which this AST file was created. + if (File == nullptr && !F.OriginalDir.empty() && !CurrentDir.empty() && + F.OriginalDir != CurrentDir) { + std::string Resolved = resolveFileRelativeToOriginalDir(Filename, + F.OriginalDir, + CurrentDir); + if (!Resolved.empty()) + File = FileMgr.getFile(Resolved); + } - // Check if there was a request to override the contents of the file - // that was part of the precompiled header. Overridding such a file - // can lead to problems when lexing using the source locations from the - // PCH. - SourceManager &SM = getSourceManager(); - if (!Overridden && SM.isFileOverridden(File)) { - if (Complain) - Error(diag::err_fe_pch_file_overridden, Filename); - // After emitting the diagnostic, recover by disabling the override so - // that the original file will be used. - SM.disableFileContentsOverride(File); - // The FileEntry is a virtual file entry with the size of the contents - // that would override the original contents. Set it to the original's - // size/time. - FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), - StoredSize, StoredTime); - } + // For an overridden file, create a virtual file with the stored + // size/timestamp. + if (Overridden && File == nullptr) { + File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); + } - bool IsOutOfDate = false; + if (File == nullptr) { + if (Complain) { + std::string ErrorStr = "could not find file '"; + ErrorStr += Filename; + ErrorStr += "' referenced by AST file"; + Error(ErrorStr.c_str()); + } + // Record that we didn't find the file. + F.InputFilesLoaded[ID-1] = InputFile::getNotFound(); + return InputFile(); + } - // For an overridden file, there is nothing to validate. - if (!Overridden && (StoredSize != File->getSize() + // Check if there was a request to override the contents of the file + // that was part of the precompiled header. Overridding such a file + // can lead to problems when lexing using the source locations from the + // PCH. + SourceManager &SM = getSourceManager(); + if (!Overridden && SM.isFileOverridden(File)) { + if (Complain) + Error(diag::err_fe_pch_file_overridden, Filename); + // After emitting the diagnostic, recover by disabling the override so + // that the original file will be used. + SM.disableFileContentsOverride(File); + // The FileEntry is a virtual file entry with the size of the contents + // that would override the original contents. Set it to the original's + // size/time. + FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), + StoredSize, StoredTime); + } + + bool IsOutOfDate = false; + + // For an overridden file, there is nothing to validate. + if (!Overridden && (StoredSize != File->getSize() #if !defined(LLVM_ON_WIN32) - // In our regression testing, the Windows file system seems to - // have inconsistent modification times that sometimes - // erroneously trigger this error-handling path. - || StoredTime != File->getModificationTime() + // In our regression testing, the Windows file system seems to + // have inconsistent modification times that sometimes + // erroneously trigger this error-handling path. + || StoredTime != File->getModificationTime() #endif - )) { - if (Complain) { - Error(diag::err_fe_pch_file_modified, Filename, F.FileName); - if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight()) { - Diag(diag::note_module_cache_path) - << PP.getHeaderSearchInfo().getModuleCachePath(); - } + )) { + if (Complain) { + // Build a list of the PCH imports that got us here (in reverse). + SmallVector<ModuleFile *, 4> ImportStack(1, &F); + while (ImportStack.back()->ImportedBy.size() > 0) + ImportStack.push_back(ImportStack.back()->ImportedBy[0]); + + // The top-level PCH is stale. + StringRef TopLevelPCHName(ImportStack.back()->FileName); + Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName); + + // Print the import stack. + if (ImportStack.size() > 1 && !Diags.isDiagnosticInFlight()) { + Diag(diag::note_pch_required_by) + << Filename << ImportStack[0]->FileName; + for (unsigned I = 1; I < ImportStack.size(); ++I) + Diag(diag::note_pch_required_by) + << ImportStack[I-1]->FileName << ImportStack[I]->FileName; } - IsOutOfDate = true; + if (!Diags.isDiagnosticInFlight()) + Diag(diag::note_pch_rebuild_required) << TopLevelPCHName; } - InputFile IF = InputFile(File, Overridden, IsOutOfDate); - - // Note that we've loaded this input file. - F.InputFilesLoaded[ID-1] = IF; - return IF; - } + IsOutOfDate = true; } - return InputFile(); + InputFile IF = InputFile(File, Overridden, IsOutOfDate); + + // Note that we've loaded this input file. + F.InputFilesLoaded[ID-1] = IF; + return IF; } const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { @@ -1751,7 +2174,7 @@ const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { std::string Filename = filenameStrRef; MaybeAddSystemRootToFilename(M, Filename); const FileEntry *File = FileMgr.getFile(Filename); - if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() && + if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() && M.OriginalDir != CurrentDir) { std::string resolved = resolveFileRelativeToOriginalDir(Filename, M.OriginalDir, @@ -1791,6 +2214,7 @@ void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, SmallVectorImpl<ImportedModule> &Loaded, + const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities) { BitstreamCursor &Stream = F.Stream; @@ -1808,20 +2232,54 @@ ASTReader::ReadControlBlock(ModuleFile &F, case llvm::BitstreamEntry::Error: Error("malformed block record in AST file"); return Failure; - case llvm::BitstreamEntry::EndBlock: - // Validate all of the non-system input files. - if (!DisableValidation) { + case llvm::BitstreamEntry::EndBlock: { + // Validate input files. + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + + // All user input files reside at the index range [0, Record[1]), and + // system input files reside at [Record[1], Record[0]). + // Record is the one from INPUT_FILE_OFFSETS. + unsigned NumInputs = Record[0]; + unsigned NumUserInputs = Record[1]; + + if (!DisableValidation && + (ValidateSystemInputs || !HSOpts.ModulesValidateOncePerBuildSession || + F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp)) { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; - // All user input files reside at the index range [0, Record[1]). - // Record is the one from INPUT_FILE_OFFSETS. - for (unsigned I = 0, N = Record[1]; I < N; ++I) { + + // If we are reading a module, we will create a verification timestamp, + // so we verify all input files. Otherwise, verify only user input + // files. + + unsigned N = NumUserInputs; + if (ValidateSystemInputs || + (HSOpts.ModulesValidateOncePerBuildSession && F.Kind == MK_Module)) + N = NumInputs; + + for (unsigned I = 0; I < N; ++I) { InputFile IF = getInputFile(F, I+1, Complain); if (!IF.getFile() || IF.isOutOfDate()) return OutOfDate; } } + + if (Listener) + Listener->visitModuleFile(F.FileName); + + if (Listener && Listener->needsInputFileVisitation()) { + unsigned N = Listener->needsSystemInputFileVisitation() ? NumInputs + : NumUserInputs; + for (unsigned I = 0; I < N; ++I) { + bool IsSystem = I >= NumUserInputs; + InputFileInfo FI = readInputFileInfo(F, I+1); + Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden); + } + } + return Success; - + } + case llvm::BitstreamEntry::SubBlock: switch (Entry.ID) { case INPUT_FILES_BLOCK_ID: @@ -1854,8 +2312,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, case METADATA: { if (Record[0] != VERSION_MAJOR && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old - : diag::warn_pch_version_too_new); + Diag(Record[0] < VERSION_MAJOR? diag::err_pch_version_too_old + : diag::err_pch_version_too_new); return VersionMismatch; } @@ -1871,7 +2329,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, StringRef ASTBranch = Blob; if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch; + Diag(diag::err_pch_different_branch) << ASTBranch << CurBranch; return VersionMismatch; } break; @@ -1916,7 +2374,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; if (Listener && &F == *ModuleMgr.begin() && ParseLanguageOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1925,17 +2383,17 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && ParseTargetOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } case DIAGNOSTIC_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; + bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0; if (Listener && &F == *ModuleMgr.begin() && ParseDiagnosticOptions(Record, Complain, *Listener) && !DisableValidation) - return ConfigurationMismatch; + return OutOfDate; break; } @@ -1943,7 +2401,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && ParseFileSystemOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1952,7 +2410,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && ParseHeaderSearchOptions(Record, Complain, *Listener) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1962,7 +2420,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, if (Listener && &F == *ModuleMgr.begin() && ParsePreprocessorOptions(Record, Complain, *Listener, SuggestedPredefines) && - !DisableValidation) + !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; } @@ -1982,6 +2440,49 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.OriginalDir = Blob; break; + case MODULE_NAME: + F.ModuleName = Blob; + if (Listener) + Listener->ReadModuleName(F.ModuleName); + break; + + case MODULE_MAP_FILE: + F.ModuleMapPath = Blob; + + // Try to resolve ModuleName in the current header search context and + // verify that it is found in the same module map file as we saved. If the + // top-level AST file is a main file, skip this check because there is no + // usable header search context. + assert(!F.ModuleName.empty() && + "MODULE_NAME should come before MOUDLE_MAP_FILE"); + if (F.Kind == MK_Module && + (*ModuleMgr.begin())->Kind != MK_MainFile) { + Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + if (!M) { + assert(ImportedBy && "top-level import should be verified"); + if ((ClientLoadCapabilities & ARR_Missing) == 0) + Diag(diag::err_imported_module_not_found) + << F.ModuleName << ImportedBy->FileName; + return Missing; + } + + const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath); + if (StoredModMap == nullptr || StoredModMap != M->ModuleMap) { + assert(M->ModuleMap && "found module is missing module map file"); + assert(M->Name == F.ModuleName && "found module with different name"); + assert(ImportedBy && "top-level import should be verified"); + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Diag(diag::err_imported_module_modmap_changed) + << F.ModuleName << ImportedBy->FileName + << M->ModuleMap->getName() << F.ModuleMapPath; + return OutOfDate; + } + } + + if (Listener) + Listener->ReadModuleMapFile(F.ModuleMapPath); + break; + case INPUT_FILE_OFFSETS: F.InputFileOffsets = (const uint32_t *)Blob.data(); F.InputFilesLoaded.resize(Record[0]); @@ -1990,12 +2491,13 @@ ASTReader::ReadControlBlock(ModuleFile &F, } } -bool ASTReader::ReadASTBlock(ModuleFile &F) { +ASTReader::ASTReadResult +ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { BitstreamCursor &Stream = F.Stream; if (Stream.EnterSubBlock(AST_BLOCK_ID)) { Error("malformed block record in AST file"); - return true; + return Failure; } // Read all of the records and blocks for the AST file. @@ -2006,7 +2508,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { switch (Entry.Kind) { case llvm::BitstreamEntry::Error: Error("error at end of module block in AST file"); - return true; + return Failure; case llvm::BitstreamEntry::EndBlock: { // Outside of C++, we do not store a lookup map for the translation unit. // Instead, mark it as needing a lookup map to be built if this module @@ -2018,7 +2520,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { !getContext().getLangOpts().CPlusPlus) DC->setMustBuildLookupTable(); - return false; + return Success; } case llvm::BitstreamEntry::SubBlock: switch (Entry.ID) { @@ -2032,17 +2534,10 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Read the abbrevs. ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) { Error("malformed block record in AST file"); - return true; - } - break; - - case DECL_UPDATES_BLOCK_ID: - if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return true; + return Failure; } break; - + case PREPROCESSOR_BLOCK_ID: F.MacroCursor = Stream; if (!PP.getExternalSource()) @@ -2051,7 +2546,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (Stream.SkipBlock() || ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) { Error("malformed block record in AST file"); - return true; + return Failure; } F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo(); break; @@ -2062,7 +2557,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { ReadBlockAbbrevs(F.PreprocessorDetailCursor, PREPROCESSOR_DETAIL_BLOCK_ID)) { Error("malformed preprocessor detail record in AST file"); - return true; + return Failure; } F.PreprocessorDetailStartOffset = F.PreprocessorDetailCursor.GetCurrentBitNo(); @@ -2075,12 +2570,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case SOURCE_MANAGER_BLOCK_ID: if (ReadSourceManagerBlock(F)) - return true; + return Failure; break; case SUBMODULE_BLOCK_ID: - if (ReadSubmoduleBlock(F)) - return true; + if (ASTReadResult Result = ReadSubmoduleBlock(F, ClientLoadCapabilities)) + return Result; break; case COMMENTS_BLOCK_ID: { @@ -2088,7 +2583,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (Stream.SkipBlock() || ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) { Error("malformed comments block in AST file"); - return true; + return Failure; } CommentsCursors.push_back(std::make_pair(C, &F)); break; @@ -2097,7 +2592,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { default: if (Stream.SkipBlock()) { Error("malformed block record in AST file"); - return true; + return Failure; } break; } @@ -2118,7 +2613,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case TYPE_OFFSET: { if (F.LocalNumTypes != 0) { Error("duplicate TYPE_OFFSET record in AST file"); - return true; + return Failure; } F.TypeOffsets = (const uint32_t *)Blob.data(); F.LocalNumTypes = Record[0]; @@ -2142,7 +2637,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case DECL_OFFSET: { if (F.LocalNumDecls != 0) { Error("duplicate DECL_OFFSET record in AST file"); - return true; + return Failure; } F.DeclOffsets = (const DeclOffset *)Blob.data(); F.LocalNumDecls = Record[0]; @@ -2183,14 +2678,18 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { unsigned Idx = 0; serialization::DeclID ID = ReadDeclID(F, Record, Idx); ASTDeclContextNameLookupTable *Table = - ASTDeclContextNameLookupTable::Create( - (const unsigned char *)Blob.data() + Record[Idx++], - (const unsigned char *)Blob.data(), - ASTDeclContextNameLookupTrait(*this, F)); - if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU? - DeclContext *TU = Context.getTranslationUnitDecl(); - F.DeclContextInfos[TU].NameLookupTableData = Table; - TU->setHasExternalVisibleStorage(true); + ASTDeclContextNameLookupTable::Create( + (const unsigned char *)Blob.data() + Record[Idx++], + (const unsigned char *)Blob.data() + sizeof(uint32_t), + (const unsigned char *)Blob.data(), + ASTDeclContextNameLookupTrait(*this, F)); + if (Decl *D = GetExistingDecl(ID)) { + auto *DC = cast<DeclContext>(D); + DC->getPrimaryContext()->setHasExternalVisibleStorage(true); + auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData; + // FIXME: There should never be an existing lookup table. + delete LookupTable; + LookupTable = Table; } else PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F)); break; @@ -2199,11 +2698,11 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case IDENTIFIER_TABLE: F.IdentifierTableData = Blob.data(); if (Record[0]) { - F.IdentifierLookupTable - = ASTIdentifierLookupTable::Create( - (const unsigned char *)F.IdentifierTableData + Record[0], - (const unsigned char *)F.IdentifierTableData, - ASTIdentifierLookupTrait(*this, F)); + F.IdentifierLookupTable = ASTIdentifierLookupTable::Create( + (const unsigned char *)F.IdentifierTableData + Record[0], + (const unsigned char *)F.IdentifierTableData + sizeof(uint32_t), + (const unsigned char *)F.IdentifierTableData, + ASTIdentifierLookupTrait(*this, F)); PP.getIdentifierTable().setExternalIdentifierLookup(this); } @@ -2212,7 +2711,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case IDENTIFIER_OFFSET: { if (F.LocalNumIdentifiers != 0) { Error("duplicate IDENTIFIER_OFFSET record in AST file"); - return true; + return Failure; } F.IdentifierOffsets = (const uint32_t *)Blob.data(); F.LocalNumIdentifiers = Record[0]; @@ -2237,9 +2736,9 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; } - case EXTERNAL_DEFINITIONS: + case EAGERLY_DESERIALIZED_DECLS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I])); + EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); break; case SPECIAL_TYPES: @@ -2251,7 +2750,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (SpecialTypes.size() != Record.size()) { Error("invalid special-types record"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; ++I) { @@ -2283,7 +2782,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case WEAK_UNDECLARED_IDENTIFIERS: if (Record.size() % 4 != 0) { Error("invalid weak identifiers record"); - return true; + return Failure; } // FIXME: Ignore weak undeclared identifiers from non-original PCH @@ -2365,7 +2864,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { F.SLocEntryOffsets = (const uint32_t *)Blob.data(); F.LocalNumSLocEntries = Record[0]; unsigned SLocSpaceSize = Record[1]; - llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = + std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, SLocSpaceSize); // Make our entry in the range map. BaseID is negative and growing, so @@ -2384,9 +2883,9 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Initialize the remapping table. // Invalid stays invalid. - F.SLocRemap.insert(std::make_pair(0U, 0)); + F.SLocRemap.insertOrReplace(std::make_pair(0U, 0)); // This module. Base was 2 when being compiled. - F.SLocRemap.insert(std::make_pair(2U, + F.SLocRemap.insertOrReplace(std::make_pair(2U, static_cast<int>(F.SLocEntryBaseOffset - 2))); TotalNumSLocEntries += F.LocalNumSLocEntries; @@ -2397,7 +2896,13 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Additional remapping information. const unsigned char *Data = (const unsigned char*)Blob.data(); const unsigned char *DataEnd = Data + Blob.size(); - + + // If we see this entry before SOURCE_LOCATION_OFFSETS, add placeholders. + if (F.SLocRemap.find(0) == F.SLocRemap.end()) { + F.SLocRemap.insert(std::make_pair(0U, 0)); + F.SLocRemap.insert(std::make_pair(2U, 1)); + } + // Continuous range maps we may be updating in our module. ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder @@ -2414,24 +2919,33 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap); while(Data < DataEnd) { - uint16_t Len = io::ReadUnalignedLE16(Data); + using namespace llvm::support; + uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data); StringRef Name = StringRef((const char*)Data, Len); Data += Len; ModuleFile *OM = ModuleMgr.lookup(Name); if (!OM) { Error("SourceLocation remap refers to unknown module"); - return true; + return Failure; } - uint32_t SLocOffset = io::ReadUnalignedLE32(Data); - uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data); - uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data); - uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data); - uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data); - uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data); - uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data); - uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data); - + uint32_t SLocOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t IdentifierIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t MacroIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t PreprocessedEntityIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t SubmoduleIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t SelectorIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t DeclIDOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + uint32_t TypeIndexOffset = + endian::readNext<uint32_t, little, unaligned>(Data); + // Source location offset is mapped to OM->SLocEntryBaseOffset. SLocRemap.insert(std::make_pair(SLocOffset, static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset))); @@ -2461,7 +2975,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case SOURCE_MANAGER_LINE_TABLE: if (ParseLineTable(F, Record)) - return true; + return Failure; break; case SOURCE_LOCATION_PRELOADS: { @@ -2469,7 +2983,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // which is based off F.SLocEntryBaseID. if (!F.PreloadSLocEntries.empty()) { Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file"); - return true; + return Failure; } F.PreloadSLocEntries.swap(Record); @@ -2484,7 +2998,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case VTABLE_USES: if (Record.size() % 3 != 0) { Error("Invalid VTABLE_USES record"); - return true; + return Failure; } // Later tables overwrite earlier ones. @@ -2508,12 +3022,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case PENDING_IMPLICIT_INSTANTIATIONS: if (PendingInstantiations.size() % 2 != 0) { Error("Invalid existing PendingInstantiations"); - return true; + return Failure; } if (Record.size() % 2 != 0) { Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { @@ -2526,7 +3040,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case SEMA_DECL_REFS: if (Record.size() != 2) { Error("Invalid SEMA_DECL_REFS block"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; ++I) SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); @@ -2567,18 +3081,24 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case DECL_UPDATE_OFFSETS: { if (Record.size() % 2 != 0) { Error("invalid DECL_UPDATE_OFFSETS block in AST file"); - return true; + return Failure; + } + for (unsigned I = 0, N = Record.size(); I != N; I += 2) { + GlobalDeclID ID = getGlobalDeclID(F, Record[I]); + DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1])); + + // If we've already loaded the decl, perform the updates when we finish + // loading this block. + if (Decl *D = GetExistingDecl(ID)) + PendingUpdateRecords.push_back(std::make_pair(ID, D)); } - for (unsigned I = 0, N = Record.size(); I != N; I += 2) - DeclUpdateOffsets[getGlobalDeclID(F, Record[I])] - .push_back(std::make_pair(&F, Record[I+1])); break; } case DECL_REPLACEMENTS: { if (Record.size() % 3 != 0) { Error("invalid DECL_REPLACEMENTS block in AST file"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; I += 3) ReplacedDecls[getGlobalDeclID(F, Record[I])] @@ -2589,7 +3109,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case OBJC_CATEGORIES_MAP: { if (F.LocalNumObjCCategoriesInMap != 0) { Error("duplicate OBJC_CATEGORIES_MAP record in AST file"); - return true; + return Failure; } F.LocalNumObjCCategoriesInMap = Record[0]; @@ -2604,7 +3124,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case CXX_BASE_SPECIFIER_OFFSETS: { if (F.LocalNumCXXBaseSpecifiers != 0) { Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file"); - return true; + return Failure; } F.LocalNumCXXBaseSpecifiers = Record[0]; @@ -2671,12 +3191,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case UNDEFINED_BUT_USED: if (UndefinedButUsed.size() % 2 != 0) { Error("Invalid existing UndefinedButUsed"); - return true; + return Failure; } if (Record.size() % 2 != 0) { Error("invalid undefined-but-used record"); - return true; + return Failure; } for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++])); @@ -2690,9 +3210,11 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // If we aren't loading a module (which has its own exports), make // all of the imported modules visible. // FIXME: Deal with macros-only imports. - for (unsigned I = 0, N = Record.size(); I != N; ++I) { - if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I])) - ImportedModules.push_back(GlobalID); + for (unsigned I = 0, N = Record.size(); I != N; /**/) { + unsigned GlobalID = getGlobalSubmoduleID(F, Record[I++]); + SourceLocation Loc = ReadSourceLocation(F, Record, I); + if (GlobalID) + ImportedModules.push_back(ImportedSubmodule(GlobalID, Loc)); } } break; @@ -2706,7 +3228,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case LOCAL_REDECLARATIONS_MAP: { if (F.LocalNumRedeclarationsInMap != 0) { Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file"); - return true; + return Failure; } F.LocalNumRedeclarationsInMap = Record[0]; @@ -2727,7 +3249,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case MACRO_OFFSET: { if (F.LocalNumMacros != 0) { Error("duplicate MACRO_OFFSET record in AST file"); - return true; + return Failure; } F.MacroOffsets = (const uint32_t *)Blob.data(); F.LocalNumMacros = Record[0]; @@ -2757,6 +3279,14 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { LateParsedTemplates.append(Record.begin(), Record.end()); break; } + + case OPTIMIZE_PRAGMA_OPTIONS: + if (Record.size() != 1) { + Error("invalid pragma optimize record"); + return Failure; + } + OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]); + break; } } } @@ -2790,31 +3320,27 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { } } -void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) { - for (unsigned I = 0, N = Names.size(); I != N; ++I) { - switch (Names[I].getKind()) { - case HiddenName::Declaration: { - Decl *D = Names[I].getDecl(); - bool wasHidden = D->Hidden; - D->Hidden = false; +void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner, + bool FromFinalization) { + // FIXME: Only do this if Owner->NameVisibility == AllVisible. + for (Decl *D : Names.HiddenDecls) { + bool wasHidden = D->Hidden; + D->Hidden = false; - if (wasHidden && SemaObj) { - if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { - moveMethodToBackOfGlobalList(*SemaObj, Method); - } + if (wasHidden && SemaObj) { + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { + moveMethodToBackOfGlobalList(*SemaObj, Method); } - break; - } - case HiddenName::MacroVisibility: { - std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro(); - installImportedMacro(Macro.first, Macro.second, Owner); - break; - } } } + + assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) && + "nothing to make visible?"); + for (const auto &Macro : Names.HiddenMacros) + installImportedMacro(Macro.first, Macro.second, Owner, FromFinalization); } -void ASTReader::makeModuleVisible(Module *Mod, +void ASTReader::makeModuleVisible(Module *Mod, Module::NameVisibilityKind NameVisibility, SourceLocation ImportLoc, bool Complain) { @@ -2829,21 +3355,28 @@ void ASTReader::makeModuleVisible(Module *Mod, // there is nothing more to do. continue; } - + if (!Mod->isAvailable()) { // Modules that aren't available cannot be made visible. continue; } // Update the module's name visibility. + if (NameVisibility >= Module::MacrosVisible && + Mod->NameVisibility < Module::MacrosVisible) + Mod->MacroVisibilityLoc = ImportLoc; Mod->NameVisibility = NameVisibility; - + // If we've already deserialized any names from this module, // mark them as visible. HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod); if (Hidden != HiddenNamesMap.end()) { - makeNamesVisible(Hidden->second, Hidden->first); + auto HiddenNames = std::move(*Hidden); HiddenNamesMap.erase(Hidden); + makeNamesVisible(HiddenNames.second, HiddenNames.first, + /*FromFinalization*/false); + assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() && + "making names visible added hidden names"); } // Push any exported modules onto the stack to be marked as visible. @@ -2899,6 +3432,17 @@ bool ASTReader::isGlobalIndexUnavailable() const { !hasGlobalIndex() && TriedLoadingGlobalIndex; } +static void updateModuleTimestamp(ModuleFile &MF) { + // Overwrite the timestamp file contents so that file's mtime changes. + std::string TimestampFilename = MF.getTimestampFilename(); + std::string ErrorInfo; + llvm::raw_fd_ostream OS(TimestampFilename.c_str(), ErrorInfo, + llvm::sys::fs::F_Text); + if (!ErrorInfo.empty()) + return; + OS << "Timestamp file\n"; +} + ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type, SourceLocation ImportLoc, @@ -2906,13 +3450,16 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, llvm::SaveAndRestore<SourceLocation> SetCurImportLocRAII(CurrentImportLoc, ImportLoc); + // Defer any pending actions until we get to the end of reading the AST file. + Deserializing AnASTFile(this); + // Bump the generation number. - unsigned PreviousGeneration = CurrentGeneration++; + unsigned PreviousGeneration = incrementGeneration(Context); unsigned NumModules = ModuleMgr.size(); SmallVector<ImportedModule, 4> Loaded; switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc, - /*ImportedBy=*/0, Loaded, + /*ImportedBy=*/nullptr, Loaded, 0, 0, ClientLoadCapabilities)) { case Failure: @@ -2920,18 +3467,23 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, case OutOfDate: case VersionMismatch: case ConfigurationMismatch: - case HadErrors: + case HadErrors: { + llvm::SmallPtrSet<ModuleFile *, 4> LoadedSet; + for (const ImportedModule &IM : Loaded) + LoadedSet.insert(IM.Mod); + ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(), + LoadedSet, Context.getLangOpts().Modules ? &PP.getHeaderSearchInfo().getModuleMap() - : 0); + : nullptr); // If we find that any modules are unusable, the global index is going // to be out-of-date. Just remove it. GlobalIndex.reset(); - ModuleMgr.setGlobalIndex(0); + ModuleMgr.setGlobalIndex(nullptr); return ReadResult; - + } case Success: break; } @@ -2945,8 +3497,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleFile &F = *M->Mod; // Read the AST block. - if (ReadASTBlock(F)) - return Failure; + if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities)) + return Result; // Once read, set the ModuleFile bit base offset and update the size in // bits of all files we've seen. @@ -3057,6 +3609,21 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, PreviousGeneration); } + if (PP.getHeaderSearchInfo() + .getHeaderSearchOpts() + .ModulesValidateOncePerBuildSession) { + // Now we are certain that the module and all modules it depends on are + // up to date. Create or update timestamp files for modules that are + // located in the module cache (not for PCH files that could be anywhere + // in the filesystem). + for (unsigned I = 0, N = Loaded.size(); I != N; ++I) { + ImportedModule &M = Loaded[I]; + if (M.Mod->Kind == MK_Module) { + updateModuleTimestamp(*M.Mod); + } + } + } + return Success; } @@ -3072,7 +3639,7 @@ ASTReader::ReadASTCore(StringRef FileName, std::string ErrorStr; ModuleManager::AddModuleResult AddResult = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, - CurrentGeneration, ExpectedSize, ExpectedModTime, + getGeneration(), ExpectedSize, ExpectedModTime, M, ErrorStr); switch (AddResult) { @@ -3162,7 +3729,7 @@ ASTReader::ReadASTCore(StringRef FileName, break; case CONTROL_BLOCK_ID: HaveReadControlBlock = true; - switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) { + switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) { case Success: break; @@ -3177,7 +3744,7 @@ ASTReader::ReadASTCore(StringRef FileName, case AST_BLOCK_ID: if (!HaveReadControlBlock) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) - Diag(diag::warn_pch_version_too_old); + Diag(diag::err_pch_version_too_old); return VersionMismatch; } @@ -3203,11 +3770,6 @@ void ASTReader::InitializeContext() { DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, Context.getTranslationUnitDecl()); - // Make sure we load the declaration update records for the translation unit, - // if there are any. - loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID, - Context.getTranslationUnitDecl()); - // FIXME: Find a better way to deal with collisions between these // built-in types. Right now, we just ignore the problem. @@ -3323,24 +3885,26 @@ void ASTReader::InitializeContext() { Context.setcudaConfigureCallDecl( cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0]))); } - + // Re-export any modules that were imported by a non-module AST file. - for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) { - if (Module *Imported = getSubmodule(ImportedModules[I])) + // FIXME: This does not make macro-only imports visible again. It also doesn't + // make #includes mapped to module imports visible. + for (auto &Import : ImportedModules) { + if (Module *Imported = getSubmodule(Import.ID)) makeModuleVisible(Imported, Module::AllVisible, - /*ImportLoc=*/SourceLocation(), + /*ImportLoc=*/Import.ImportLoc, /*Complain=*/false); } ImportedModules.clear(); } void ASTReader::finalizeForWriting() { - for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(), - HiddenEnd = HiddenNamesMap.end(); - Hidden != HiddenEnd; ++Hidden) { - makeNamesVisible(Hidden->second, Hidden->first); + while (!HiddenNamesMap.empty()) { + auto HiddenNames = std::move(*HiddenNamesMap.begin()); + HiddenNamesMap.erase(HiddenNamesMap.begin()); + makeNamesVisible(HiddenNames.second, HiddenNames.first, + /*FromFinalization*/true); } - HiddenNamesMap.clear(); } /// \brief Given a cursor at the start of an AST file, scan ahead and drop the @@ -3381,7 +3945,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, DiagnosticsEngine &Diags) { // Open the AST file. std::string ErrStr; - OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr)); if (!Buffer) { Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr; @@ -3448,18 +4012,18 @@ namespace { { } - virtual bool ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain) { - return checkLanguageOptions(ExistingLangOpts, LangOpts, 0); + bool ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) override { + return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr); } - virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain) { - return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0); + bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) override { + return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr); } - virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, - bool Complain, - std::string &SuggestedPredefines) { - return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr, + bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines) override { + return checkPreprocessorOptions(ExistingPPOpts, PPOpts, nullptr, FileMgr, SuggestedPredefines, ExistingLangOpts); } }; @@ -3470,7 +4034,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, ASTReaderListener &Listener) { // Open the AST file. std::string ErrStr; - OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr)); if (!Buffer) { return true; @@ -3496,6 +4060,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, return true; bool NeedsInputFiles = Listener.needsInputFileVisitation(); + bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation(); BitstreamCursor InputFilesCursor; if (NeedsInputFiles) { InputFilesCursor = Stream; @@ -3539,6 +4104,12 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, break; } + case MODULE_NAME: + Listener.ReadModuleName(Blob); + break; + case MODULE_MAP_FILE: + Listener.ReadModuleMapFile(Blob); + break; case LANGUAGE_OPTIONS: if (ParseLanguageOptions(Record, false, Listener)) return true; @@ -3582,6 +4153,10 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, for (unsigned I = 0; I != NumInputFiles; ++I) { // Go find this input file. bool isSystemFile = I >= NumUserFiles; + + if (isSystemFile && !NeedsSystemInputFiles) + break; // the rest are system input files + BitstreamCursor &Cursor = InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(InputFileOffs[I]); @@ -3592,7 +4167,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, bool shouldContinue = false; switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { case INPUT_FILE: - shouldContinue = Listener.visitInputFile(Blob, isSystemFile); + bool Overridden = static_cast<bool>(Record[3]); + shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden); break; } if (!shouldContinue) @@ -3618,16 +4194,17 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename, return !readASTFileControlBlock(Filename, FileMgr, validator); } -bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { +ASTReader::ASTReadResult +ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Enter the submodule block. if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) { Error("malformed submodule block record in AST file"); - return true; + return Failure; } ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); bool First = true; - Module *CurrentModule = 0; + Module *CurrentModule = nullptr; RecordData Record; while (true) { llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks(); @@ -3636,9 +4213,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: Error("malformed block record in AST file"); - return true; + return Failure; case llvm::BitstreamEntry::EndBlock: - return false; + return Success; case llvm::BitstreamEntry::Record: // The interesting case. break; @@ -3654,39 +4231,47 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_DEFINITION: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (Record.size() < 8) { Error("malformed module definition"); - return true; + return Failure; } StringRef Name = Blob; - SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]); - SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]); - bool IsFramework = Record[2]; - bool IsExplicit = Record[3]; - bool IsSystem = Record[4]; - bool InferSubmodules = Record[5]; - bool InferExplicitSubmodules = Record[6]; - bool InferExportWildcard = Record[7]; - bool ConfigMacrosExhaustive = Record[8]; - - Module *ParentModule = 0; - if (Parent) + unsigned Idx = 0; + SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]); + SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]); + bool IsFramework = Record[Idx++]; + bool IsExplicit = Record[Idx++]; + bool IsSystem = Record[Idx++]; + bool IsExternC = Record[Idx++]; + bool InferSubmodules = Record[Idx++]; + bool InferExplicitSubmodules = Record[Idx++]; + bool InferExportWildcard = Record[Idx++]; + bool ConfigMacrosExhaustive = Record[Idx++]; + + Module *ParentModule = nullptr; + const FileEntry *ModuleMap = nullptr; + if (Parent) { ParentModule = getSubmodule(Parent); - + ModuleMap = ParentModule->ModuleMap; + } + + if (!F.ModuleMapPath.empty()) + ModuleMap = FileMgr.getFile(F.ModuleMapPath); + // Retrieve this (sub)module from the module map, creating it if // necessary. - CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, + CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, ModuleMap, IsFramework, IsExplicit).first; SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; if (GlobalIndex >= SubmodulesLoaded.size() || SubmodulesLoaded[GlobalIndex]) { Error("too many submodules"); - return true; + return Failure; } if (!ParentModule) { @@ -3698,15 +4283,16 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { << CurFile->getName() << F.File->getName(); } - return true; + return Failure; } } CurrentModule->setASTFile(F.File); } - + CurrentModule->IsFromModuleFile = true; CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; + CurrentModule->IsExternC = IsExternC; CurrentModule->InferSubmodules = InferSubmodules; CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; CurrentModule->InferExportWildcard = InferExportWildcard; @@ -3727,7 +4313,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_UMBRELLA_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3737,8 +4323,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule->getUmbrellaHeader()) ModMap.setUmbrellaHeader(CurrentModule, Umbrella); else if (CurrentModule->getUmbrellaHeader() != Umbrella) { - Error("mismatched umbrella headers in submodule"); - return true; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Error("mismatched umbrella headers in submodule"); + return OutOfDate; } } break; @@ -3747,7 +4334,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3762,7 +4349,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_EXCLUDED_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3777,7 +4364,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_PRIVATE_HEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3792,7 +4379,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_TOPHEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3805,7 +4392,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_UMBRELLA_DIR: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3816,8 +4403,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule->getUmbrellaDir()) ModMap.setUmbrellaDir(CurrentModule, Umbrella); else if (CurrentModule->getUmbrellaDir() != Umbrella) { - Error("mismatched umbrella directories in submodule"); - return true; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Error("mismatched umbrella directories in submodule"); + return OutOfDate; } } break; @@ -3826,7 +4414,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_METADATA: { if (!First) { Error("submodule metadata record not at beginning of block"); - return true; + return Failure; } First = false; @@ -3852,7 +4440,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_IMPORTS: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3873,7 +4461,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_EXPORTS: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3897,7 +4485,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_REQUIRES: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3911,7 +4499,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_LINK_LIBRARY: if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3924,7 +4512,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_CONFIG_MACRO: if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -3936,7 +4524,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { case SUBMODULE_CONFLICT: { if (First) { Error("missing submodule metadata record at beginning of block"); - return true; + return Failure; } if (!CurrentModule) @@ -4004,8 +4592,6 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record, TargetOpts.Triple = ReadString(Record, Idx); TargetOpts.CPU = ReadString(Record, Idx); TargetOpts.ABI = ReadString(Record, Idx); - TargetOpts.CXXABI = ReadString(Record, Idx); - TargetOpts.LinkerVersion = ReadString(Record, Idx); for (unsigned N = Record[Idx++]; N; --N) { TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx)); } @@ -4018,16 +4604,17 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record, bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain, ASTReaderListener &Listener) { - DiagnosticOptions DiagOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions); unsigned Idx = 0; -#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++]; +#define DIAGOPT(Name, Bits, Default) DiagOpts->Name = Record[Idx++]; #define ENUM_DIAGOPT(Name, Type, Bits, Default) \ - DiagOpts.set##Name(static_cast<Type>(Record[Idx++])); + DiagOpts->set##Name(static_cast<Type>(Record[Idx++])); #include "clang/Basic/DiagnosticOptions.def" - for (unsigned N = Record[Idx++]; N; --N) { - DiagOpts.Warnings.push_back(ReadString(Record, Idx)); - } + for (unsigned N = Record[Idx++]; N; --N) + DiagOpts->Warnings.push_back(ReadString(Record, Idx)); + for (unsigned N = Record[Idx++]; N; --N) + DiagOpts->Remarks.push_back(ReadString(Record, Idx)); return Listener.ReadDiagnosticOptions(DiagOpts, Complain); } @@ -4068,6 +4655,7 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, HSOpts.ResourceDir = ReadString(Record, Idx); HSOpts.ModuleCachePath = ReadString(Record, Idx); + HSOpts.ModuleUserBuildPath = ReadString(Record, Idx); HSOpts.DisableModuleHash = Record[Idx++]; HSOpts.UseBuiltinIncludes = Record[Idx++]; HSOpts.UseStandardSystemIncludes = Record[Idx++]; @@ -4149,7 +4737,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { if (!PP.getPreprocessingRecord()) { Error("no preprocessing record"); - return 0; + return nullptr; } SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); @@ -4158,7 +4746,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { llvm::BitstreamEntry Entry = M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); if (Entry.Kind != llvm::BitstreamEntry::Record) - return 0; + return nullptr; // Read the record. SourceRange Range(ReadSourceLocation(M, PPOffs.Begin), @@ -4172,8 +4760,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { switch (RecType) { case PPD_MACRO_EXPANSION: { bool isBuiltin = Record[0]; - IdentifierInfo *Name = 0; - MacroDefinition *Def = 0; + IdentifierInfo *Name = nullptr; + MacroDefinition *Def = nullptr; if (isBuiltin) Name = getLocalIdentifier(M, Record[1]); else { @@ -4207,7 +4795,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { case PPD_INCLUSION_DIRECTIVE: { const char *FullFileNameStart = Blob.data() + Record[0]; StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]); - const FileEntry *File = 0; + const FileEntry *File = nullptr; if (!FullFileName.empty()) File = PP.getFileManager().getFile(FullFileName); @@ -4276,15 +4864,13 @@ struct PPEntityComp { } -/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc. -PreprocessedEntityID -ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { - if (SourceMgr.isLocalSourceLocation(BLoc)) +PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc, + bool EndsAfter) const { + if (SourceMgr.isLocalSourceLocation(Loc)) return getTotalNumPreprocessedEntities(); - GlobalSLocOffsetMapType::const_iterator - SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - - BLoc.getOffset() - 1); + GlobalSLocOffsetMapType::const_iterator SLocMapI = GlobalSLocOffsetMap.find( + SourceManager::MaxLoadedOffset - Loc.getOffset() - 1); assert(SLocMapI != GlobalSLocOffsetMap.end() && "Corrupted global sloc offset map"); @@ -4301,21 +4887,26 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { pp_iterator First = pp_begin; pp_iterator PPI; - // Do a binary search manually instead of using std::lower_bound because - // The end locations of entities may be unordered (when a macro expansion - // is inside another macro argument), but for this case it is not important - // whether we get the first macro expansion or its containing macro. - while (Count > 0) { - Half = Count/2; - PPI = First; - std::advance(PPI, Half); - if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End), - BLoc)){ - First = PPI; - ++First; - Count = Count - Half - 1; - } else - Count = Half; + if (EndsAfter) { + PPI = std::upper_bound(pp_begin, pp_end, Loc, + PPEntityComp<&PPEntityOffset::Begin>(*this, M)); + } else { + // Do a binary search manually instead of using std::lower_bound because + // The end locations of entities may be unordered (when a macro expansion + // is inside another macro argument), but for this case it is not important + // whether we get the first macro expansion or its containing macro. + while (Count > 0) { + Half = Count / 2; + PPI = First; + std::advance(PPI, Half); + if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End), + Loc)) { + First = PPI; + ++First; + Count = Count - Half - 1; + } else + Count = Half; + } } if (PPI == pp_end) @@ -4324,35 +4915,6 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { return M.BasePreprocessedEntityID + (PPI - pp_begin); } -/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc. -PreprocessedEntityID -ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const { - if (SourceMgr.isLocalSourceLocation(ELoc)) - return getTotalNumPreprocessedEntities(); - - GlobalSLocOffsetMapType::const_iterator - SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - - ELoc.getOffset() - 1); - assert(SLocMapI != GlobalSLocOffsetMap.end() && - "Corrupted global sloc offset map"); - - if (SLocMapI->second->NumPreprocessedEntities == 0) - return findNextPreprocessedEntity(SLocMapI); - - ModuleFile &M = *SLocMapI->second; - typedef const PPEntityOffset *pp_iterator; - pp_iterator pp_begin = M.PreprocessedEntityOffsets; - pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; - pp_iterator PPI = - std::upper_bound(pp_begin, pp_end, ELoc, - PPEntityComp<&PPEntityOffset::Begin>(*this, M)); - - if (PPI == pp_end) - return findNextPreprocessedEntity(SLocMapI); - - return M.BasePreprocessedEntityID + (PPI - pp_begin); -} - /// \brief Returns a pair of [Begin, End) indices of preallocated /// preprocessed entities that \arg Range encompasses. std::pair<unsigned, unsigned> @@ -4361,8 +4923,9 @@ std::pair<unsigned, unsigned> return std::make_pair(0,0); assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); - PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin()); - PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd()); + PreprocessedEntityID BeginID = + findPreprocessedEntity(Range.getBegin(), false); + PreprocessedEntityID EndID = findPreprocessedEntity(Range.getEnd(), true); return std::make_pair(BeginID, EndID); } @@ -4468,9 +5031,9 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { if (DiagID == (unsigned)-1) { break; // no more diag/map pairs for this location. } - diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++]; - DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc); - Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo); + diag::Severity Map = (diag::Severity)F.PragmaDiagMappings[Idx++]; + DiagnosticMapping Mapping = Diag.makeUserMapping(Map, Loc); + Diag.GetCurDiagState()->setMapping(DiagID, Mapping); } } } @@ -4548,6 +5111,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return DT; } + case TYPE_ADJUSTED: { + if (Record.size() != 2) { + Error("Incorrect encoding of adjusted type"); + return QualType(); + } + QualType OriginalTy = readType(*Loc.F, Record, Idx); + QualType AdjustedTy = readType(*Loc.F, Record, Idx); + return Context.getAdjustedType(OriginalTy, AdjustedTy); + } + case TYPE_BLOCK_POINTER: { if (Record.size() != 1) { Error("Incorrect encoding of block pointer type"); @@ -4671,23 +5244,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) { EPI.HasTrailingReturn = Record[Idx++]; EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]); - ExceptionSpecificationType EST = - static_cast<ExceptionSpecificationType>(Record[Idx++]); - EPI.ExceptionSpecType = EST; - SmallVector<QualType, 2> Exceptions; - if (EST == EST_Dynamic) { - EPI.NumExceptions = Record[Idx++]; - for (unsigned I = 0; I != EPI.NumExceptions; ++I) - Exceptions.push_back(readType(*Loc.F, Record, Idx)); - EPI.Exceptions = Exceptions.data(); - } else if (EST == EST_ComputedNoexcept) { - EPI.NoexceptExpr = ReadExpr(*Loc.F); - } else if (EST == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); - EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); - } else if (EST == EST_Unevaluated) { - EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); - } + SmallVector<QualType, 8> ExceptionStorage; + readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx); return Context.getFunctionType(ResultType, ParamTypes, EPI); } @@ -4837,9 +5395,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) { unsigned Idx = 0; QualType Parm = readType(*Loc.F, Record, Idx); QualType Replacement = readType(*Loc.F, Record, Idx); - return - Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), - Replacement); + return Context.getSubstTemplateTypeParmType( + cast<TemplateTypeParmType>(Parm), + Context.getCanonicalType(Replacement)); } case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: { @@ -4856,8 +5414,14 @@ QualType ASTReader::readTypeRecord(unsigned Index) { QualType TST = readType(*Loc.F, Record, Idx); // probably derivable // FIXME: ASTContext::getInjectedClassNameType is not currently suitable // for AST reading, too much interdependencies. - return - QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0); + const Type *T; + if (const Type *Existing = D->getTypeForDecl()) + T = Existing; + else if (auto *Prev = D->getPreviousDecl()) + T = Prev->getTypeForDecl(); + else + T = new (Context, TypeAlignment) InjectedClassNameType(D, TST); + return QualType(T, 0); } case TYPE_TEMPLATE_TYPE_PARM: { @@ -4942,6 +5506,29 @@ QualType ASTReader::readTypeRecord(unsigned Index) { llvm_unreachable("Invalid TypeCode!"); } +void ASTReader::readExceptionSpec(ModuleFile &ModuleFile, + SmallVectorImpl<QualType> &Exceptions, + FunctionProtoType::ExtProtoInfo &EPI, + const RecordData &Record, unsigned &Idx) { + ExceptionSpecificationType EST = + static_cast<ExceptionSpecificationType>(Record[Idx++]); + EPI.ExceptionSpecType = EST; + if (EST == EST_Dynamic) { + EPI.NumExceptions = Record[Idx++]; + for (unsigned I = 0; I != EPI.NumExceptions; ++I) + Exceptions.push_back(readType(ModuleFile, Record, Idx)); + EPI.Exceptions = Exceptions.data(); + } else if (EST == EST_ComputedNoexcept) { + EPI.NoexceptExpr = ReadExpr(ModuleFile); + } else if (EST == EST_Uninstantiated) { + EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + EPI.ExceptionSpecTemplate = + ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + } else if (EST == EST_Unevaluated) { + EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + } +} + class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { ASTReader &Reader; ModuleFile &F; @@ -4997,6 +5584,9 @@ void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) { // nothing to do } +void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { + // nothing to do +} void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { TL.setCaretLoc(ReadSourceLocation(Record, Idx)); } @@ -5016,7 +5606,7 @@ void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { if (Record[Idx++]) TL.setSizeExpr(Reader.ReadExpr(F)); else - TL.setSizeExpr(0); + TL.setSizeExpr(nullptr); } void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { VisitArrayTypeLoc(TL); @@ -5046,8 +5636,8 @@ void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { TL.setLParenLoc(ReadSourceLocation(Record, Idx)); TL.setRParenLoc(ReadSourceLocation(Record, Idx)); TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx)); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { - TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); + for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) { + TL.setParam(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); } } void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { @@ -5103,7 +5693,7 @@ void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { if (Record[Idx++]) TL.setAttrExprOperand(Reader.ReadExpr(F)); else - TL.setAttrExprOperand(0); + TL.setAttrExprOperand(nullptr); } else if (TL.hasAttrEnumOperand()) TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx)); } @@ -5187,7 +5777,7 @@ TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F, unsigned &Idx) { QualType InfoTy = readType(F, Record, Idx); if (InfoTy.isNull()) - return 0; + return nullptr; TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); TypeLocReader TLR(*this, F, Record, Idx); @@ -5374,11 +5964,54 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } -uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, - unsigned &Idx){ - if (Idx >= Record.size()) +void ASTReader::CompleteRedeclChain(const Decl *D) { + if (NumCurrentElementsDeserializing) { + // We arrange to not care about the complete redeclaration chain while we're + // deserializing. Just remember that the AST has marked this one as complete + // but that it's not actually complete yet, so we know we still need to + // complete it later. + PendingIncompleteDeclChains.push_back(const_cast<Decl*>(D)); + return; + } + + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + + // Recursively ensure that the decl context itself is complete + // (in particular, this matters if the decl context is a namespace). + // + // FIXME: This should be performed by lookup instead of here. + cast<Decl>(DC)->getMostRecentDecl(); + + // If this is a named declaration, complete it by looking it up + // within its context. + // + // FIXME: We don't currently handle the cases where we can't do this; + // merging a class definition that contains unnamed entities should merge + // those entities. Likewise, merging a function definition should merge + // all mergeable entities within it. + if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) || + isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) { + if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) { + auto *II = Name.getAsIdentifierInfo(); + if (isa<TranslationUnitDecl>(DC) && II) { + // Outside of C++, we don't have a lookup table for the TU, so update + // the identifier instead. In C++, either way should work fine. + if (II->isOutOfDate()) + updateOutOfDateIdentifier(*II); + } else + DC->lookup(Name); + } + } +} + +uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, + const RecordData &Record, + unsigned &Idx) { + if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXBaseSpecifiers) { + Error("malformed AST file: missing C++ base specifier"); return 0; - + } + unsigned LocalID = Record[Idx++]; return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]); } @@ -5393,8 +6026,8 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { unsigned Code = Cursor.ReadCode(); unsigned RecCode = Cursor.readRecord(Code, Record); if (RecCode != DECL_CXX_BASE_SPECIFIERS) { - Error("Malformed AST file: missing C++ base specifiers"); - return 0; + Error("malformed AST file: missing C++ base specifiers"); + return nullptr; } unsigned Idx = 0; @@ -5427,7 +6060,7 @@ bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { if (!D->isFromASTFile()) - return 0; + return nullptr; GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); return I->second; @@ -5436,14 +6069,14 @@ ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { if (ID < NUM_PREDEF_DECL_IDS) return SourceLocation(); - + unsigned Index = ID - NUM_PREDEF_DECL_IDS; if (Index > DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); return SourceLocation(); } - + if (Decl *D = DeclsLoaded[Index]) return D->getLocation(); @@ -5452,15 +6085,15 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { return ReadSourceLocation(*Rec.F, RawLocation); } -Decl *ASTReader::GetDecl(DeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) { +Decl *ASTReader::GetExistingDecl(DeclID ID) { + if (ID < NUM_PREDEF_DECL_IDS) { switch ((PredefinedDeclIDs)ID) { case PREDEF_DECL_NULL_ID: - return 0; - + return nullptr; + case PREDEF_DECL_TRANSLATION_UNIT_ID: return Context.getTranslationUnitDecl(); - + case PREDEF_DECL_OBJC_ID_ID: return Context.getObjCIdDecl(); @@ -5469,16 +6102,16 @@ Decl *ASTReader::GetDecl(DeclID ID) { case PREDEF_DECL_OBJC_CLASS_ID: return Context.getObjCClassDecl(); - + case PREDEF_DECL_OBJC_PROTOCOL_ID: return Context.getObjCProtocolDecl(); - + case PREDEF_DECL_INT_128_ID: return Context.getInt128Decl(); case PREDEF_DECL_UNSIGNED_INT_128_ID: return Context.getUInt128Decl(); - + case PREDEF_DECL_OBJC_INSTANCETYPE_ID: return Context.getObjCInstanceTypeDecl(); @@ -5486,15 +6119,30 @@ Decl *ASTReader::GetDecl(DeclID ID) { return Context.getBuiltinVaListDecl(); } } - + unsigned Index = ID - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); Error("declaration ID out-of-range for AST file"); - return 0; + return nullptr; } - + + return DeclsLoaded[Index]; +} + +Decl *ASTReader::GetDecl(DeclID ID) { + if (ID < NUM_PREDEF_DECL_IDS) + return GetExistingDecl(ID); + + unsigned Index = ID - NUM_PREDEF_DECL_IDS; + + if (Index >= DeclsLoaded.size()) { + assert(0 && "declaration ID out-of-range for AST file"); + Error("declaration ID out-of-range for AST file"); + return nullptr; + } + if (!DeclsLoaded[Index]) { ReadDeclRecord(ID); if (DeserializationListener) @@ -5779,7 +6427,7 @@ static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC, if (const DeclContext *DefDC = getDefinitiveDeclContext(DC)) return Reader.getOwningModuleFile(cast<Decl>(DefDC)); - return 0; + return nullptr; } bool @@ -5800,14 +6448,19 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, Contexts.push_back(DC); if (DC->isNamespace()) { - MergedDeclsMap::iterator Merged - = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); + auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); if (Merged != MergedDecls.end()) { for (unsigned I = 0, N = Merged->second.size(); I != N; ++I) Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I]))); } } - + if (isa<CXXRecordDecl>(DC)) { + auto Merged = MergedLookups.find(DC); + if (Merged != MergedLookups.end()) + Contexts.insert(Contexts.end(), Merged->second.begin(), + Merged->second.end()); + } + DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); // If we can definitively determine which module file to look into, @@ -5924,15 +6577,23 @@ static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD, ASTConsumer *Consumer) { assert(ImplD && Consumer); - for (ObjCImplDecl::method_iterator - I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I) - Consumer->HandleInterestingDecl(DeclGroupRef(*I)); + for (auto *I : ImplD->methods()) + Consumer->HandleInterestingDecl(DeclGroupRef(I)); Consumer->HandleInterestingDecl(DeclGroupRef(ImplD)); } void ASTReader::PassInterestingDeclsToConsumer() { assert(Consumer); + + if (PassingDeclsToConsumer) + return; + + // Guard variable to avoid recursively redoing the process of passing + // decls to consumer. + SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, + true); + while (!InterestingDecls.empty()) { Decl *D = InterestingDecls.front(); InterestingDecls.pop_front(); @@ -5954,12 +6615,12 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) { if (!Consumer) return; - for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { + for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) { // Force deserialization of this decl, which will cause it to be queued for // passing to the consumer. - GetDecl(ExternalDefinitions[I]); + GetDecl(EagerlyDeserializedDecls[I]); } - ExternalDefinitions.clear(); + EagerlyDeserializedDecls.clear(); PassInterestingDeclsToConsumer(); } @@ -5972,15 +6633,15 @@ void ASTReader::PrintStats() { QualType()); unsigned NumDeclsLoaded = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), - (Decl *)0); + (Decl *)nullptr); unsigned NumIdentifiersLoaded = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), IdentifiersLoaded.end(), - (IdentifierInfo *)0); + (IdentifierInfo *)nullptr); unsigned NumMacrosLoaded = MacrosLoaded.size() - std::count(MacrosLoaded.begin(), MacrosLoaded.end(), - (MacroInfo *)0); + (MacroInfo *)nullptr); unsigned NumSelectorsLoaded = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), SelectorsLoaded.end(), @@ -6164,6 +6825,11 @@ void ASTReader::UpdateSema() { } SemaDeclRefs.clear(); } + + // Update the state of 'pragma clang optimize'. Use the same API as if we had + // encountered the pragma in the source. + if(OptimizeOffPragmaLocation.isValid()) + SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation); } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { @@ -6174,7 +6840,7 @@ IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { // If there is a global index, look there first to determine which modules // provably do not have any results for this identifier. GlobalModuleIndex::HitSet Hits; - GlobalModuleIndex::HitSet *HitsPtr = 0; + GlobalModuleIndex::HitSet *HitsPtr = nullptr; if (!loadGlobalIndex()) { if (GlobalIndex->lookupIdentifier(Name, Hits)) { HitsPtr = &Hits; @@ -6211,7 +6877,7 @@ namespace clang { public: explicit ASTIdentifierIterator(const ASTReader &Reader); - virtual StringRef Next(); + StringRef Next() override; }; } @@ -6330,7 +6996,7 @@ void ASTReader::ReadMethodPool(Selector Sel) { // Get the selector generation and update it to the current generation. unsigned &Generation = SelectorGeneration[Sel]; unsigned PriorGeneration = Generation; - Generation = CurrentGeneration; + Generation = getGeneration(); // Search for methods defined with this selector. ++NumMethodPoolLookups; @@ -6587,11 +7253,11 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { if (ID == 0) - return 0; + return nullptr; if (IdentifiersLoaded.empty()) { Error("no identifier table in AST file"); - return 0; + return nullptr; } ID -= 1; @@ -6637,11 +7303,11 @@ IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { MacroInfo *ASTReader::getMacro(MacroID ID) { if (ID == 0) - return 0; + return nullptr; if (MacrosLoaded.empty()) { Error("no macro table in AST file"); - return 0; + return nullptr; } ID -= NUM_PREDEF_MACRO_IDS; @@ -6688,12 +7354,12 @@ ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) { assert(GlobalID == 0 && "Unhandled global submodule ID"); - return 0; + return nullptr; } if (GlobalID > SubmodulesLoaded.size()) { Error("submodule ID out of range in AST file"); - return 0; + return nullptr; } return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; @@ -6716,7 +7382,7 @@ Selector ASTReader::DecodeSelector(serialization::SelectorID ID) { return Selector(); } - if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) { + if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == nullptr) { // Load this selector from the selector table. GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID); assert(I != GlobalSelectorMap.end() && "Corrupted global selector map"); @@ -7012,16 +7678,16 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, std::pair<CXXCtorInitializer **, unsigned> ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx) { - CXXCtorInitializer **CtorInitializers = 0; + CXXCtorInitializer **CtorInitializers = nullptr; unsigned NumInitializers = Record[Idx++]; if (NumInitializers) { CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *TInfo = 0; + TypeSourceInfo *TInfo = nullptr; bool IsBaseVirtual = false; - FieldDecl *Member = 0; - IndirectFieldDecl *IndirectMember = 0; + FieldDecl *Member = nullptr; + IndirectFieldDecl *IndirectMember = nullptr; CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; switch (Type) { @@ -7101,7 +7767,7 @@ NestedNameSpecifier * ASTReader::ReadNestedNameSpecifier(ModuleFile &F, const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; - NestedNameSpecifier *NNS = 0, *Prev = 0; + NestedNameSpecifier *NNS = nullptr, *Prev = nullptr; for (unsigned I = 0; I != N; ++I) { NestedNameSpecifier::SpecifierKind Kind = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; @@ -7128,8 +7794,8 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F, case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *T = readType(F, Record, Idx).getTypePtrOrNull(); if (!T) - return 0; - + return nullptr; + bool Template = Record[Idx++]; NNS = NestedNameSpecifier::Create(Context, Prev, Template, T); break; @@ -7276,14 +7942,14 @@ IdentifierTable &ASTReader::getIdentifierTable() { /// \brief Record that the given ID maps to the given switch-case /// statement. void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] == 0 && + assert((*CurrSwitchCaseStmts)[ID] == nullptr && "Already have a SwitchCase with this ID"); (*CurrSwitchCaseStmts)[ID] = SC; } /// \brief Retrieve the switch-case statement with the given ID. SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) { - assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID"); + assert((*CurrSwitchCaseStmts)[ID] != nullptr && "No SwitchCase with this ID"); return (*CurrSwitchCaseStmts)[ID]; } @@ -7298,6 +7964,7 @@ void ASTReader::ReadComments() { I = CommentsCursors.begin(), E = CommentsCursors.end(); I != E; ++I) { + Comments.clear(); BitstreamCursor &Cursor = I->first; serialization::ModuleFile &F = *I->second; SavedStreamPosition SavedPosition(Cursor); @@ -7306,7 +7973,7 @@ void ASTReader::ReadComments() { while (true) { llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); - + switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: @@ -7336,15 +8003,29 @@ void ASTReader::ReadComments() { } } } - NextCursor:; + NextCursor: + Context.Comments.addDeserializedComments(Comments); } - Context.Comments.addCommentsToFront(Comments); +} + +std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { + // If we know the owning module, use it. + if (Module *M = D->getOwningModule()) + return M->getFullModuleName(); + + // Otherwise, use the name of the top-level module the decl is within. + if (ModuleFile *M = getOwningModuleFile(D)) + return M->ModuleName; + + // Not from a module. + return ""; } void ASTReader::finishPendingActions() { - while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() || + while (!PendingIdentifierInfos.empty() || + !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingOdrMergeChecks.empty()) { + !PendingUpdateRecords.empty() || !PendingOdrMergeChecks.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > @@ -7352,14 +8033,21 @@ void ASTReader::finishPendingActions() { TopLevelDeclsMap TopLevelDecls; while (!PendingIdentifierInfos.empty()) { - // FIXME: std::move IdentifierInfo *II = PendingIdentifierInfos.back().first; - SmallVector<uint32_t, 4> DeclIDs = PendingIdentifierInfos.back().second; + SmallVector<uint32_t, 4> DeclIDs = + std::move(PendingIdentifierInfos.back().second); PendingIdentifierInfos.pop_back(); SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]); } - + + // For each decl chain that we wanted to complete while deserializing, mark + // it as "still needs to be completed". + for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { + markIncompleteDeclChain(PendingIncompleteDeclChains[I]); + } + PendingIncompleteDeclChains.clear(); + // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) { loadPendingDeclChain(PendingDeclChains[I]); @@ -7382,14 +8070,14 @@ void ASTReader::finishPendingActions() { SmallVector<PendingMacroInfo, 2> GlobalIDs; GlobalIDs.swap(PendingMacroIDs.begin()[I].second); // Initialize the macro history from chained-PCHs ahead of module imports. - for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; + for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; if (Info.M->Kind != MK_Module) resolvePendingMacro(II, Info); } // Handle module imports. - for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; + for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { const PendingMacroInfo &Info = GlobalIDs[IDIdx]; if (Info.M->Kind == MK_Module) @@ -7408,6 +8096,30 @@ void ASTReader::finishPendingActions() { Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext()); } + // Perform any pending declaration updates. + // + // Don't do this if we have known-incomplete redecl chains: it relies on + // being able to walk redeclaration chains. + while (PendingDeclChains.empty() && !PendingUpdateRecords.empty()) { + auto Update = PendingUpdateRecords.pop_back_val(); + ReadingKindTracker ReadingKind(Read_Decl, *this); + loadDeclUpdateRecords(Update.first, Update.second); + } + + // Trigger the import of the full definition of each class that had any + // odr-merging problems, so we can produce better diagnostics for them. + for (auto &Merge : PendingOdrMergeFailures) { + Merge.first->buildLookup(); + Merge.first->decls_begin(); + Merge.first->bases_begin(); + Merge.first->vbases_begin(); + for (auto *RD : Merge.second) { + RD->decls_begin(); + RD->bases_begin(); + RD->vbases_begin(); + } + } + // For each declaration from a merged context, check that the canonical // definition of that context also contains a declaration of the same // entity. @@ -7430,16 +8142,14 @@ void ASTReader::finishPendingActions() { llvm::SmallVector<const NamedDecl*, 4> Candidates; for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); !Found && I != E; ++I) { - for (Decl::redecl_iterator RI = (*I)->redecls_begin(), - RE = (*I)->redecls_end(); - RI != RE; ++RI) { - if ((*RI)->getLexicalDeclContext() == CanonDef) { + for (auto RI : (*I)->redecls()) { + if (RI->getLexicalDeclContext() == CanonDef) { // This declaration is present in the canonical definition. If it's // in the same redecl chain, it's the one we're looking for. - if ((*RI)->getCanonicalDecl() == DCanon) + if (RI->getCanonicalDecl() == DCanon) Found = true; else - Candidates.push_back(cast<NamedDecl>(*RI)); + Candidates.push_back(cast<NamedDecl>(RI)); break; } } @@ -7448,11 +8158,11 @@ void ASTReader::finishPendingActions() { if (!Found) { D->setInvalidDecl(); - Module *CanonDefModule = cast<Decl>(CanonDef)->getOwningModule(); + std::string CanonDefModule = + getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) - << D << D->getOwningModule()->getFullModuleName() - << CanonDef << !CanonDefModule - << (CanonDefModule ? CanonDefModule->getFullModuleName() : ""); + << D << getOwningModuleNameForDiagnostic(D) + << CanonDef << CanonDefModule.empty() << CanonDefModule; if (Candidates.empty()) Diag(cast<Decl>(CanonDef)->getLocation(), @@ -7463,6 +8173,8 @@ void ASTReader::finishPendingActions() { diag::note_module_odr_violation_possible_decl) << Candidates[I]; } + + DiagnosedOdrMergeFailures.insert(CanonDef); } } } @@ -7475,49 +8187,39 @@ void ASTReader::finishPendingActions() { DEnd = PendingDefinitions.end(); D != DEnd; ++D) { if (TagDecl *TD = dyn_cast<TagDecl>(*D)) { - if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) { + if (const TagType *TagT = dyn_cast<TagType>(TD->getTypeForDecl())) { // Make sure that the TagType points at the definition. const_cast<TagType*>(TagT)->decl = TD; } - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) { - for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(), - REnd = RD->redecls_end(); - R != REnd; ++R) - cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData; - + if (auto RD = dyn_cast<CXXRecordDecl>(*D)) { + for (auto R : RD->redecls()) + cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData; } continue; } - if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) { + if (auto ID = dyn_cast<ObjCInterfaceDecl>(*D)) { // Make sure that the ObjCInterfaceType points at the definition. const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl)) ->Decl = ID; - for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), - REnd = ID->redecls_end(); - R != REnd; ++R) + for (auto R : ID->redecls()) R->Data = ID->Data; continue; } - if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) { - for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(), - REnd = PD->redecls_end(); - R != REnd; ++R) + if (auto PD = dyn_cast<ObjCProtocolDecl>(*D)) { + for (auto R : PD->redecls()) R->Data = PD->Data; continue; } - RedeclarableTemplateDecl *RTD - = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); - for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(), - REnd = RTD->redecls_end(); - R != REnd; ++R) + auto RTD = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); + for (auto R : RTD->redecls()) R->Common = RTD->Common; } PendingDefinitions.clear(); @@ -7541,6 +8243,46 @@ void ASTReader::finishPendingActions() { MD->setLazyBody(PB->second); } PendingBodies.clear(); + + // Issue any pending ODR-failure diagnostics. + for (auto &Merge : PendingOdrMergeFailures) { + if (!DiagnosedOdrMergeFailures.insert(Merge.first)) + continue; + + bool Diagnosed = false; + for (auto *RD : Merge.second) { + // Multiple different declarations got merged together; tell the user + // where they came from. + if (Merge.first != RD) { + // FIXME: Walk the definition, figure out what's different, + // and diagnose that. + if (!Diagnosed) { + std::string Module = getOwningModuleNameForDiagnostic(Merge.first); + Diag(Merge.first->getLocation(), + diag::err_module_odr_violation_different_definitions) + << Merge.first << Module.empty() << Module; + Diagnosed = true; + } + + Diag(RD->getLocation(), + diag::note_module_odr_violation_different_definitions) + << getOwningModuleNameForDiagnostic(RD); + } + } + + if (!Diagnosed) { + // All definitions are updates to the same declaration. This happens if a + // module instantiates the declaration of a class template specialization + // and two or more other modules instantiate its definition. + // + // FIXME: Indicate which modules had instantiations of this definition. + // FIXME: How can this even happen? + Diag(Merge.first->getLocation(), + diag::err_module_odr_violation_different_instantiations) + << Merge.first; + } + } + PendingOdrMergeFailures.clear(); } void ASTReader::FinishedDeserializing() { @@ -7553,20 +8295,10 @@ void ASTReader::FinishedDeserializing() { } --NumCurrentElementsDeserializing; - if (NumCurrentElementsDeserializing == 0 && - Consumer && !PassingDeclsToConsumer) { - // Guard variable to avoid recursively redoing the process of passing - // decls to consumer. - SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); - - while (!InterestingDecls.empty()) { - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - Decl *D = InterestingDecls.front(); - InterestingDecls.pop_front(); - PassInterestingDeclToConsumer(D); - } + if (NumCurrentElementsDeserializing == 0 && Consumer) { + // We are not in recursive loading, so it's safe to pass the "interesting" + // decls to the consumer. + PassInterestingDeclsToConsumer(); } } @@ -7585,34 +8317,39 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { } } -ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, bool DisableValidation, - bool AllowASTWithCompilerErrors, bool UseGlobalIndex) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), - Consumer(0), ModuleMgr(PP.getFileManager()), - isysroot(isysroot), DisableValidation(DisableValidation), - AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), - UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false), - CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts), - NumSLocEntriesRead(0), TotalNumSLocEntries(0), - NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), - TotalNumMacros(0), NumIdentifierLookups(0), NumIdentifierLookupHits(0), - NumSelectorsRead(0), NumMethodPoolEntriesRead(0), - NumMethodPoolLookups(0), NumMethodPoolHits(0), - NumMethodPoolTableLookups(0), NumMethodPoolTableHits(0), - TotalNumMethodPoolEntries(0), - NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), - NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), - TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), - PassingDeclsToConsumer(false), - NumCXXBaseSpecifiersLoaded(0), ReadingKind(Read_None) -{ +ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, + bool DisableValidation, bool AllowASTWithCompilerErrors, + bool AllowConfigurationMismatch, bool ValidateSystemInputs, + bool UseGlobalIndex) + : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr), + OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()), + FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), + SemaObj(nullptr), PP(PP), Context(Context), Consumer(nullptr), + ModuleMgr(PP.getFileManager()), isysroot(isysroot), + DisableValidation(DisableValidation), + AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), + AllowConfigurationMismatch(AllowConfigurationMismatch), + ValidateSystemInputs(ValidateSystemInputs), + UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false), + CurrSwitchCaseStmts(&SwitchCaseStmts), + NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0), + TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0), + NumIdentifierLookups(0), NumIdentifierLookupHits(0), NumSelectorsRead(0), + NumMethodPoolEntriesRead(0), NumMethodPoolLookups(0), + NumMethodPoolHits(0), NumMethodPoolTableLookups(0), + NumMethodPoolTableHits(0), TotalNumMethodPoolEntries(0), + NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), + NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), + TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), + PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0), + ReadingKind(Read_None) { SourceMgr.setExternalSLocEntrySource(this); } ASTReader::~ASTReader() { + if (OwnsDeserializationListener) + delete DeserializationListener; + for (DeclContextVisibleUpdatesPending::iterator I = PendingVisibleUpdates.begin(), E = PendingVisibleUpdates.end(); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index b8102d8..9ed1bf9 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -99,16 +99,19 @@ namespace clang { Module *readModule(const RecordData &R, unsigned &I) { return Reader.getSubmodule(readSubmoduleID(R, I)); } - + + void ReadCXXRecordDefinition(CXXRecordDecl *D); void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, const RecordData &R, unsigned &I); + void MergeDefinitionData(CXXRecordDecl *D, + struct CXXRecordDecl::DefinitionData &NewDD); /// \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. /// - /// The caller can choose not to introduce this ID into the redeclaration - /// chain by calling \c suppress(). + /// The caller can choose not to introduce this ID into the list of pending + /// redeclaration chains by calling \c suppress(). class RedeclarableResult { ASTReader &Reader; GlobalDeclID FirstID; @@ -160,8 +163,8 @@ namespace clang { public: FindExistingResult(ASTReader &Reader) - : Reader(Reader), New(0), Existing(0), AddResult(false) { } - + : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false) {} + FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing) : Reader(Reader), New(New), Existing(Existing), AddResult(true) { } @@ -195,9 +198,20 @@ namespace clang { RawLocation(RawLocation), Record(Record), Idx(Idx), TypeIDForTypeDecl(0), HasPendingBody(false) { } + template <typename DeclT> + static void attachPreviousDeclImpl(Redeclarable<DeclT> *D, Decl *Previous); + static void attachPreviousDeclImpl(...); static void attachPreviousDecl(Decl *D, Decl *previous); + + template <typename DeclT> + static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest); + static void attachLatestDeclImpl(...); static void attachLatestDecl(Decl *D, Decl *latest); + template <typename DeclT> + static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D); + static void markIncompleteDeclChainImpl(...); + /// \brief Determine whether this declaration has a pending body. bool hasPendingBody() const { return HasPendingBody; } @@ -264,7 +278,7 @@ namespace clang { void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - void VisitTemplateDecl(TemplateDecl *D); + DeclID VisitTemplateDecl(TemplateDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitVarTemplateDecl(VarTemplateDecl *D); @@ -285,20 +299,26 @@ namespace clang { void VisitEmptyDecl(EmptyDecl *D); std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); - - template<typename T> + + template<typename T> RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); template<typename T> - void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); + void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl, + DeclID TemplatePatternID = 0); template<typename T> void mergeRedeclarable(Redeclarable<T> *D, T *Existing, - RedeclarableResult &Redecl); + RedeclarableResult &Redecl, + DeclID TemplatePatternID = 0); template<typename T> void mergeMergeable(Mergeable<T> *D); + void mergeTemplatePattern(RedeclarableTemplateDecl *D, + RedeclarableTemplateDecl *Existing, + DeclID DsID); + // FIXME: Reorder according to DeclNodes.td? void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCContainerDecl(ObjCContainerDecl *D); @@ -337,7 +357,7 @@ void ASTDeclReader::Visit(Decl *D) { } if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { - // if we have a fully initialized TypeDecl, we can safely read its type now. + // We have a fully initialized TypeDecl. Read its type now. TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. @@ -356,11 +376,14 @@ void ASTDeclReader::Visit(Decl *D) { } void ASTDeclReader::VisitDecl(Decl *D) { - if (D->isTemplateParameter()) { + if (D->isTemplateParameter() || D->isTemplateParameterPack() || + isa<ParmVarDecl>(D)) { // We don't want to deserialize the DeclContext of a template - // parameter immediately, because the template parameter might be - // used in the formulation of its DeclContext. Use the translation - // unit DeclContext as a placeholder. + // parameter or of a parameter of a function template immediately. These + // entities might be used in the formulation of its DeclContext (for + // example, a function parameter can be used in decltype() in trailing + // return type of the function). Use the translation unit DeclContext as a + // placeholder. GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx); GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx); Reader.addPendingDeclContextInfo(D, @@ -409,7 +432,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { // Note that this declaration was hidden because its owning module is // not yet visible. - Reader.HiddenNamesMap[Owner].push_back(D); + Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D); } } } @@ -471,7 +494,8 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { } else TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx); - mergeRedeclarable(TD, Redecl); + if (!isa<CXXRecordDecl>(TD)) + mergeRedeclarable(TD, Redecl); return Redecl; } @@ -573,9 +597,10 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { case FunctionDecl::TK_NonTemplate: - mergeRedeclarable(FD, Redecl); + mergeRedeclarable(FD, Redecl); break; case FunctionDecl::TK_FunctionTemplate: + // Merged when we merge the template. FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record, Idx)); break; @@ -585,6 +610,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { SourceLocation POI = ReadSourceLocation(Record, Idx); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + mergeRedeclarable(FD, Redecl); break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { @@ -622,7 +648,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FunctionTemplateSpecializationInfo *FTInfo = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, TemplArgList, - HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0, + HasTemplateArgumentsAsWritten ? &TemplArgsInfo + : nullptr, POI); FD->TemplateOrSpecialization = FTInfo; @@ -637,9 +664,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // We avoid getASTContext because a decl in the parent hierarchy may // be initializing. llvm::FoldingSetNodeID ID; - FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(), - TemplArgs.size(), C); - void *InsertPos = 0; + FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs, C); + void *InsertPos = nullptr; FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr(); CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos); if (InsertPos) @@ -670,6 +696,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setDependentTemplateSpecialization(Reader.getContext(), TemplDecls, TemplArgs); + + // FIXME: Merging. break; } } @@ -709,8 +737,8 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); MD->SetRelatedResultType(Record[Idx++]); - MD->setResultType(Reader.readType(F, Record, Idx)); - MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + MD->setReturnType(Reader.readType(F, Record, Idx)); + MD->setReturnTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); MD->DeclEndLoc = ReadSourceLocation(Record, Idx); unsigned NumParams = Record[Idx++]; SmallVector<ParmVarDecl *, 16> Params; @@ -755,6 +783,7 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { Data.SuperClassLoc = ReadSourceLocation(Record, Idx); Data.EndLoc = ReadSourceLocation(Record, Idx); + Data.HasDesignatedInitializers = Record[Idx++]; // Read the directly referenced protocols and their SourceLocations. unsigned NumProtocols = Record[Idx++]; @@ -779,8 +808,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { Reader.getContext()); // We will rebuild this list lazily. - ID->setIvarList(0); - + ID->setIvarList(nullptr); + // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(ID); @@ -795,11 +824,9 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { VisitFieldDecl(IVD); IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]); // This field will be built lazily. - IVD->setNextIvar(0); + IVD->setNextIvar(nullptr); bool synth = Record[Idx++]; IVD->setSynthesize(synth); - bool backingIvarReferencedInAccessor = Record[Idx++]; - IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor); } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { @@ -907,8 +934,8 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); D->setHasNonZeroConstructors(Record[Idx++]); D->setHasDestructors(Record[Idx++]); - llvm::tie(D->IvarInitializers, D->NumIvarInitializers) - = Reader.ReadCXXCtorInitializers(F, Record, Idx); + std::tie(D->IvarInitializers, D->NumIvarInitializers) = + Reader.ReadCXXCtorInitializers(F, Record, Idx); } @@ -971,14 +998,10 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->setCachedLinkage(VarLinkage); // Reconstruct the one piece of the IdentifierNamespace that we need. - if (VarLinkage != NoLinkage && + if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage && VD->getLexicalDeclContext()->isFunctionOrMethod()) VD->setLocalExternDecl(); - // Only true variables (not parameters or implicit parameters) can be merged. - if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam) - mergeRedeclarable(VD, Redecl); - if (uint64_t Val = Record[Idx++]) { VD->setInit(Reader.ReadExpr(F)); if (Val > 1) { @@ -993,8 +1016,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { }; switch ((VarKind)Record[Idx++]) { case VarNotTemplate: + // Only true variables (not parameters or implicit parameters) can be merged + if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam && + !isa<VarTemplateSpecializationDecl>(VD)) + mergeRedeclarable(VD, Redecl); break; case VarTemplate: + // Merged when we merge the template. VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx)); break; case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo. @@ -1002,6 +1030,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); + mergeRedeclarable(VD, Redecl); break; } } @@ -1065,7 +1094,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { unsigned flags = Record[Idx++]; bool byRef = (flags & 1); bool nested = (flags & 2); - Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : 0); + Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : nullptr); captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr)); } @@ -1075,9 +1104,15 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) { VisitDecl(CD); + unsigned ContextParamPos = Record[Idx++]; + CD->setNothrow(Record[Idx++] != 0); // Body is set by VisitCapturedStmt. - for (unsigned i = 0; i < CD->NumParams; ++i) - CD->setParam(i, ReadDeclAs<ImplicitParamDecl>(Record, Idx)); + for (unsigned I = 0; I < CD->NumParams; ++I) { + if (I != ContextParamPos) + CD->setParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx)); + else + CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx)); + } } void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { @@ -1099,8 +1134,6 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { D->setInline(Record[Idx++]); D->LocStart = ReadSourceLocation(Record, Idx); D->RBraceLoc = ReadSourceLocation(Record, Idx); - // FIXME: At the point of this call, D->getCanonicalDecl() returns 0. - mergeRedeclarable(D, Redecl); if (Redecl.getFirstID() == ThisDeclID) { // Each module has its own anonymous namespace, which is disjoint from @@ -1114,6 +1147,8 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // been deserialized. D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl()); } + + mergeRedeclarable(D, Redecl); } void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { @@ -1186,6 +1221,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.HasProtectedFields = Record[Idx++]; Data.HasPublicFields = Record[Idx++]; Data.HasMutableFields = Record[Idx++]; + Data.HasVariantMembers = Record[Idx++]; Data.HasOnlyCMembers = Record[Idx++]; Data.HasInClassInitializer = Record[Idx++]; Data.HasUninitializedReferenceMember = Record[Idx++]; @@ -1196,6 +1232,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.DefaultedMoveAssignmentIsDeleted = Record[Idx++]; Data.DefaultedDestructorIsDeleted = Record[Idx++]; Data.HasTrivialSpecialMembers = Record[Idx++]; + Data.DeclaredNonTrivialSpecialMembers = Record[Idx++]; Data.HasIrrelevantDestructor = Record[Idx++]; Data.HasConstexprNonCopyMoveConstructor = Record[Idx++]; Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++]; @@ -1222,7 +1259,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.FirstFriend = ReadDeclID(Record, Idx); if (Data.IsLambda) { - typedef LambdaExpr::Capture Capture; + typedef LambdaCapture Capture; CXXRecordDecl::LambdaDefinitionData &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); Lambda.Dependent = Record[Idx++]; @@ -1242,7 +1279,7 @@ void ASTDeclReader::ReadCXXDefinitionData( LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]); switch (Kind) { case LCK_This: - *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation()); + *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation()); break; case LCK_ByCopy: case LCK_ByRef: @@ -1255,61 +1292,172 @@ void ASTDeclReader::ReadCXXDefinitionData( } } +void ASTDeclReader::MergeDefinitionData( + CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &MergeDD) { + assert(D->DefinitionData.getNotUpdated() && + "merging class definition into non-definition"); + auto &DD = *D->DefinitionData.getNotUpdated(); + + // 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) { + Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition); + DD.Definition->setHasExternalVisibleStorage(); + } + + // FIXME: Move this out into a .def file? + // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than + // asserting; this can happen in the case of an ODR violation. + bool DetectedOdrViolation = false; +#define OR_FIELD(Field) DD.Field |= MergeDD.Field; +#define MATCH_FIELD(Field) \ + DetectedOdrViolation |= DD.Field != MergeDD.Field; \ + OR_FIELD(Field) + MATCH_FIELD(UserDeclaredConstructor) + MATCH_FIELD(UserDeclaredSpecialMembers) + MATCH_FIELD(Aggregate) + MATCH_FIELD(PlainOldData) + MATCH_FIELD(Empty) + MATCH_FIELD(Polymorphic) + MATCH_FIELD(Abstract) + MATCH_FIELD(IsStandardLayout) + MATCH_FIELD(HasNoNonEmptyBases) + MATCH_FIELD(HasPrivateFields) + MATCH_FIELD(HasProtectedFields) + MATCH_FIELD(HasPublicFields) + MATCH_FIELD(HasMutableFields) + MATCH_FIELD(HasVariantMembers) + MATCH_FIELD(HasOnlyCMembers) + MATCH_FIELD(HasInClassInitializer) + MATCH_FIELD(HasUninitializedReferenceMember) + MATCH_FIELD(NeedOverloadResolutionForMoveConstructor) + MATCH_FIELD(NeedOverloadResolutionForMoveAssignment) + MATCH_FIELD(NeedOverloadResolutionForDestructor) + MATCH_FIELD(DefaultedMoveConstructorIsDeleted) + MATCH_FIELD(DefaultedMoveAssignmentIsDeleted) + MATCH_FIELD(DefaultedDestructorIsDeleted) + OR_FIELD(HasTrivialSpecialMembers) + OR_FIELD(DeclaredNonTrivialSpecialMembers) + MATCH_FIELD(HasIrrelevantDestructor) + OR_FIELD(HasConstexprNonCopyMoveConstructor) + MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr) + OR_FIELD(HasConstexprDefaultConstructor) + MATCH_FIELD(HasNonLiteralTypeFieldsOrBases) + // ComputedVisibleConversions is handled below. + MATCH_FIELD(UserProvidedDefaultConstructor) + OR_FIELD(DeclaredSpecialMembers) + MATCH_FIELD(ImplicitCopyConstructorHasConstParam) + MATCH_FIELD(ImplicitCopyAssignmentHasConstParam) + OR_FIELD(HasDeclaredCopyConstructorWithConstParam) + OR_FIELD(HasDeclaredCopyAssignmentWithConstParam) + MATCH_FIELD(IsLambda) +#undef OR_FIELD +#undef MATCH_FIELD + + if (DD.NumBases != MergeDD.NumBases || DD.NumVBases != MergeDD.NumVBases) + DetectedOdrViolation = true; + // FIXME: Issue a diagnostic if the base classes don't match when we come + // to lazily load them. + + // FIXME: Issue a diagnostic if the list of conversion functions doesn't + // match when we come to lazily load them. + if (MergeDD.ComputedVisibleConversions && !DD.ComputedVisibleConversions) { + DD.VisibleConversions = std::move(MergeDD.VisibleConversions); + DD.ComputedVisibleConversions = true; + } + + // FIXME: Issue a diagnostic if FirstFriend doesn't match when we come to + // lazily load it. + + if (DD.IsLambda) { + // FIXME: ODR-checking for merging lambdas (this happens, for instance, + // when they occur within the body of a function template specialization). + } + + if (DetectedOdrViolation) + Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition); +} + +void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { + struct CXXRecordDecl::DefinitionData *DD; + ASTContext &C = Reader.getContext(); + + // Determine whether this is a lambda closure type, so that we can + // allocate the appropriate DefinitionData structure. + bool IsLambda = Record[Idx++]; + if (IsLambda) + DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false, + LCD_None); + else + DD = new (C) struct CXXRecordDecl::DefinitionData(D); + + ReadCXXDefinitionData(*DD, Record, Idx); + + // If we're reading an update record, we might already have a definition for + // this record. If so, just merge into it. + if (D->DefinitionData.getNotUpdated()) { + MergeDefinitionData(D, *DD); + return; + } + + // Propagate the DefinitionData pointer to the canonical declaration, so + // that all other deserialized declarations will see it. + CXXRecordDecl *Canon = D->getCanonicalDecl(); + if (Canon == D) { + D->DefinitionData = DD; + D->IsCompleteDefinition = true; + } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) { + // We have already deserialized a definition of this record. This + // definition is no longer really a definition. Note that the pre-existing + // definition is the *real* definition. + Reader.MergedDeclContexts.insert( + std::make_pair(D, CanonDD->Definition)); + D->DefinitionData = Canon->DefinitionData; + D->IsCompleteDefinition = false; + MergeDefinitionData(D, *DD); + } else { + Canon->DefinitionData = DD; + D->DefinitionData = Canon->DefinitionData; + D->IsCompleteDefinition = true; + + // Note that we have deserialized a definition. Any declarations + // deserialized before this one will be be given the DefinitionData + // pointer at the end. + Reader.PendingDefinitions.insert(D); + } +} + ASTDeclReader::RedeclarableResult ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { RedeclarableResult Redecl = VisitRecordDeclImpl(D); ASTContext &C = Reader.getContext(); - bool WasDefinition = Record[Idx++]; - if (WasDefinition) { - // Determine whether this is a lambda closure type, so that we can - // allocate the appropriate DefinitionData structure. - bool IsLambda = Record[Idx++]; - if (IsLambda) - D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0, - false, - false, LCD_None); - else - D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); - - ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); - - // Propagate the DefinitionData pointer to the canonical declaration, so - // that all other deserialized declarations will see it. - CXXRecordDecl *Canon = D->getCanonicalDecl(); - if (Canon == D) { - // Nothing to do. - } else if (!Canon->DefinitionData) { - Canon->DefinitionData = D->DefinitionData; - - // Note that we have deserialized a definition. Any declarations - // deserialized before this one will be be given the DefinitionData - // pointer at the end. - Reader.PendingDefinitions.insert(D); - } else { - // We have already deserialized a definition of this record. This - // definition is no longer really a definition. Note that the pre-existing - // definition is the *real* definition. - // FIXME: Check DefinitionData for consistency with prior definition. - Reader.MergedDeclContexts.insert( - std::make_pair(D, D->getCanonicalDecl()->DefinitionData->Definition)); - D->IsCompleteDefinition = false; - D->DefinitionData = D->getCanonicalDecl()->DefinitionData; - } - } else { - // Propagate DefinitionData pointer from the canonical declaration. - D->DefinitionData = D->getCanonicalDecl()->DefinitionData; - } enum CXXRecKind { CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization }; switch ((CXXRecKind)Record[Idx++]) { case CXXRecNotTemplate: + // Merged when we merge the folding set entry in the primary template. + if (!isa<ClassTemplateSpecializationDecl>(D)) + mergeRedeclarable(D, Redecl); + break; + case CXXRecTemplate: { + // Merged when we merge the template. + ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>(Record, Idx); + D->TemplateOrInstantiation = Template; + if (!Template->getTemplatedDecl()) { + // We've not actually loaded the ClassTemplateDecl yet, because we're + // currently being loaded as its pattern. Rely on it to set up our + // TypeForDecl (see VisitClassTemplateDecl). + // + // Beware: we do not yet know our canonical declaration, and may still + // get merged once the surrounding class template has got off the ground. + TypeIDForTypeDecl = 0; + } break; - case CXXRecTemplate: - D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx); - break; + } case CXXRecMemberSpecialization: { CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; @@ -1317,15 +1465,26 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK); MSI->setPointOfInstantiation(POI); D->TemplateOrInstantiation = MSI; + mergeRedeclarable(D, Redecl); break; } } + bool WasDefinition = Record[Idx++]; + if (WasDefinition) + ReadCXXRecordDefinition(D); + else + // Propagate DefinitionData pointer from the canonical declaration. + D->DefinitionData = D->getCanonicalDecl()->DefinitionData; + // Lazily load the key function to avoid deserializing every method so we can // compute it. if (WasDefinition) { DeclID KeyFn = ReadDeclID(Record, Idx); if (KeyFn && D->IsCompleteDefinition) + // FIXME: This is wrong for the ARM ABI, where some other module may have + // made this function no longer be a key function. We need an update + // record or similar for that case. C.KeyFunctions[D] = KeyFn; } @@ -1345,10 +1504,13 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); - + + if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx)) + D->setInheritedConstructor(CD); D->IsExplicitSpecified = Record[Idx++]; - llvm::tie(D->CtorInitializers, D->NumCtorInitializers) - = Reader.ReadCXXCtorInitializers(F, Record, Idx); + // FIXME: We should defer loading this until we need the constructor's body. + std::tie(D->CtorInitializers, D->NumCtorInitializers) = + Reader.ReadCXXCtorInitializers(F, Record, Idx); } void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { @@ -1404,16 +1566,19 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { D->FriendLoc = ReadSourceLocation(Record, Idx); } -void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { +DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - NamedDecl *TemplatedDecl = ReadDeclAs<NamedDecl>(Record, Idx); + DeclID PatternID = ReadDeclID(Record, Idx); + NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); TemplateParameterList* TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); D->init(TemplatedDecl, TemplateParams); // FIXME: If this is a redeclaration of a template from another module, handle // inheritance of default template arguments. + + return PatternID; } ASTDeclReader::RedeclarableResult @@ -1442,10 +1607,10 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { } } - VisitTemplateDecl(D); + DeclID PatternID = VisitTemplateDecl(D); D->IdentifierNamespace = Record[Idx++]; - mergeRedeclarable(D, Redecl); + mergeRedeclarable(D, Redecl, PatternID); // If we merged the template with a prior declaration chain, merge the common // pointer. @@ -1486,8 +1651,14 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), SpecIDs.size() * sizeof(DeclID)); } - - CommonPtr->InjectedClassNameType = Reader.readType(F, Record, Idx); + } + + if (D->getTemplatedDecl()->TemplateOrInstantiation) { + // We were loaded before our templated declaration was. We've not set up + // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct + // it now. + Reader.Context.getInjectedClassNameType( + D->getTemplatedDecl(), D->getInjectedClassNameSpecialization()); } } @@ -1580,18 +1751,18 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( // This declaration might be a definition. Merge with any existing // definition. - if (D->DefinitionData) { - if (!CanonSpec->DefinitionData) { - CanonSpec->DefinitionData = D->DefinitionData; - } else { - // FIXME: Check DefinitionData for consistency with prior definition + if (auto *DDD = D->DefinitionData.getNotUpdated()) { + if (auto *CanonDD = CanonSpec->DefinitionData.getNotUpdated()) { + MergeDefinitionData(CanonSpec, *DDD); Reader.PendingDefinitions.erase(D); Reader.MergedDeclContexts.insert( - std::make_pair(D, CanonSpec->DefinitionData->Definition)); + std::make_pair(D, CanonDD->Definition)); D->IsCompleteDefinition = false; - D->DefinitionData = CanonSpec->DefinitionData; + } else { + CanonSpec->DefinitionData = D->DefinitionData; } } + D->DefinitionData = CanonSpec->DefinitionData; } } } @@ -1838,65 +2009,111 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { /// \brief Attempts to merge the given declaration (D) with another declaration /// of the same entity. template<typename T> -void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, - RedeclarableResult &Redecl) { +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, + RedeclarableResult &Redecl, + DeclID TemplatePatternID) { + T *D = static_cast<T*>(DBase); + T *DCanon = D->getCanonicalDecl(); + if (D != DCanon && + (!Reader.getContext().getLangOpts().Modules || + Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) { + // All redeclarations between this declaration and its originally-canonical + // declaration get pulled in when we load DCanon; we don't need to + // perform any more merging now. + Redecl.suppress(); + } + // If modules are not available, there is no reason to perform this merge. if (!Reader.getContext().getLangOpts().Modules) return; - if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) + if (FindExistingResult ExistingRes = findExisting(D)) if (T *Existing = ExistingRes) - mergeRedeclarable(D, Existing, Redecl); + mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); +} + +/// \brief "Cast" to type T, asserting if we don't have an implicit conversion. +/// We use this to put code in a template that will only be valid for certain +/// instantiations. +template<typename T> static T assert_cast(T t) { return t; } +template<typename T> static T assert_cast(...) { + llvm_unreachable("bad assert_cast"); +} + +/// \brief Merge together the pattern declarations from two template +/// declarations. +void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, + RedeclarableTemplateDecl *Existing, + DeclID DsID) { + auto *DPattern = D->getTemplatedDecl(); + auto *ExistingPattern = Existing->getTemplatedDecl(); + RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(), + DPattern->getKind()); + if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) { + // Merge with any existing definition. + // FIXME: This is duplicated in several places. Refactor. + auto *ExistingClass = + cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl(); + if (auto *DDD = DClass->DefinitionData.getNotUpdated()) { + if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) { + MergeDefinitionData(ExistingClass, *DDD); + Reader.PendingDefinitions.erase(DClass); + Reader.MergedDeclContexts.insert( + std::make_pair(DClass, ExistingDD->Definition)); + DClass->IsCompleteDefinition = false; + } else { + ExistingClass->DefinitionData = DClass->DefinitionData; + } + } + DClass->DefinitionData = ExistingClass->DefinitionData; + + return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern), + Result); + } + if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern)) + return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern), + Result); + if (auto *DVar = dyn_cast<VarDecl>(DPattern)) + return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result); + llvm_unreachable("merged an unknown kind of redeclarable template"); } /// \brief Attempts to merge the given declaration (D) with another declaration /// of the same entity. template<typename T> -void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing, - RedeclarableResult &Redecl) { +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, + RedeclarableResult &Redecl, + DeclID TemplatePatternID) { + T *D = static_cast<T*>(DBase); T *ExistingCanon = Existing->getCanonicalDecl(); - T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); + T *DCanon = D->getCanonicalDecl(); if (ExistingCanon != DCanon) { + assert(DCanon->getGlobalID() == Redecl.getFirstID()); + // Have our redeclaration link point back at the canonical declaration - // of the existing declaration, so that this declaration has the + // of the existing declaration, so that this declaration has the // appropriate canonical declaration. D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon); // When we merge a namespace, update its pointer to the first namespace. - if (NamespaceDecl *Namespace - = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) { + if (auto *Namespace = dyn_cast<NamespaceDecl>(D)) Namespace->AnonOrFirstNamespaceAndInline.setPointer( - static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon))); - } + assert_cast<NamespaceDecl*>(ExistingCanon)); - // Don't introduce DCanon into the set of pending declaration chains. - Redecl.suppress(); - - // Introduce ExistingCanon into the set of pending declaration chains, - // if in fact it came from a module file. - if (ExistingCanon->isFromASTFile()) { - GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID(); - assert(ExistingCanonID && "Unrecorded canonical declaration ID?"); - if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID)) - Reader.PendingDeclChains.push_back(ExistingCanonID); - } + // When we merge a template, merge its pattern. + if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D)) + mergeTemplatePattern( + DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon), + TemplatePatternID); // If this declaration was the canonical declaration, make a note of // that. We accept the linear algorithm here because the number of // unique canonical declarations of an entity should always be tiny. - if (DCanon == static_cast<T*>(D)) { + if (DCanon == D) { SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) == Merged.end()) Merged.push_back(Redecl.getFirstID()); - - // If ExistingCanon did not come from a module file, introduce the - // first declaration that *does* come from a module file to the - // set of pending declaration chains, so that we merge this - // declaration. - if (!ExistingCanon->isFromASTFile() && - Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID())) - Reader.PendingDeclChains.push_back(Merged[0]); } } } @@ -1942,7 +2159,7 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs, const RecordData &Record, unsigned &Idx) { for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) { - Attr *New = 0; + Attr *New = nullptr; attr::Kind Kind = (attr::Kind)Record[Idx++]; SourceRange Range = ReadSourceRange(F, Record, Idx); @@ -1981,7 +2198,8 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) { if (isa<FileScopeAsmDecl>(D) || isa<ObjCProtocolDecl>(D) || - isa<ObjCImplDecl>(D)) + isa<ObjCImplDecl>(D) || + isa<ImportDecl>(D)) return true; if (VarDecl *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && @@ -2143,9 +2361,7 @@ 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. More generally, diagnose if we - // get a declaration in a class definition that isn't in the canonical class - // definition. + // 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()); } @@ -2175,9 +2391,10 @@ static DeclContext *getPrimaryContextForMerging(DeclContext *DC) { return RD->getDefinition(); if (EnumDecl *ED = dyn_cast<EnumDecl>(DC)) - return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : 0; + return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() + : nullptr; - return 0; + return nullptr; } ASTDeclReader::FindExistingResult::~FindExistingResult() { @@ -2198,7 +2415,9 @@ 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=*/0); + FindExistingResult Result(Reader, D, /*Existing=*/nullptr); + // FIXME: We may still need to pull in the redeclaration chain; there can + // be redeclarations via 'decltype'. Result.suppress(); return Result; } @@ -2252,33 +2471,34 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // If this declaration is from a merged context, make a note that we need to // check that the canonical definition of that context contains the decl. + // + // 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())) Reader.PendingOdrMergeChecks.push_back(D); - return FindExistingResult(Reader, D, /*Existing=*/0); + return FindExistingResult(Reader, D, /*Existing=*/nullptr); } -void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { - assert(D && previous); - if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - TD->RedeclLink.setNext(cast<TagDecl>(previous)); - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - FD->RedeclLink.setNext(cast<FunctionDecl>(previous)); - } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - VD->RedeclLink.setNext(cast<VarDecl>(previous)); - } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { - TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous)); - } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { - USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous)); - } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { - ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous)); - } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { - PD->RedeclLink.setNext(cast<ObjCProtocolDecl>(previous)); - } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { - ND->RedeclLink.setNext(cast<NamespaceDecl>(previous)); - } else { - RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); - TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(previous)); +template<typename DeclT> +void ASTDeclReader::attachPreviousDeclImpl(Redeclarable<DeclT> *D, + Decl *Previous) { + D->RedeclLink.setPrevious(cast<DeclT>(Previous)); +} +void ASTDeclReader::attachPreviousDeclImpl(...) { + llvm_unreachable("attachPreviousDecl on non-redeclarable declaration"); +} + +void ASTDeclReader::attachPreviousDecl(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); \ + break; +#include "clang/AST/DeclNodes.inc" } // If the declaration was visible in one module, a redeclaration of it in @@ -2287,46 +2507,78 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { // FIXME: In this case, the declaration should only be visible if a module // that makes it visible has been imported. D->IdentifierNamespace |= - previous->IdentifierNamespace & + Previous->IdentifierNamespace & (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); + + // If the previous declaration is marked as used, then this declaration should + // 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> +void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) { + D->RedeclLink.setLatest(cast<DeclT>(Latest)); +} +void ASTDeclReader::attachLatestDeclImpl(...) { + llvm_unreachable("attachLatestDecl on non-redeclarable declaration"); } void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { assert(D && Latest); - if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - TD->RedeclLink - = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest)); - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - FD->RedeclLink - = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest)); - } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - VD->RedeclLink - = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest)); - } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { - TD->RedeclLink - = Redeclarable<TypedefNameDecl>::LatestDeclLink( - cast<TypedefNameDecl>(Latest)); - } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { - USD->RedeclLink - = Redeclarable<UsingShadowDecl>::LatestDeclLink( - cast<UsingShadowDecl>(Latest)); - } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { - ID->RedeclLink - = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink( - cast<ObjCInterfaceDecl>(Latest)); - } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { - PD->RedeclLink - = Redeclarable<ObjCProtocolDecl>::LatestDeclLink( - cast<ObjCProtocolDecl>(Latest)); - } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { - ND->RedeclLink - = Redeclarable<NamespaceDecl>::LatestDeclLink( - cast<NamespaceDecl>(Latest)); - } else { - RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); - TD->RedeclLink - = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink( - cast<RedeclarableTemplateDecl>(Latest)); + + switch (D->getKind()) { +#define ABSTRACT_DECL(TYPE) +#define DECL(TYPE, BASE) \ + case Decl::TYPE: \ + attachLatestDeclImpl(cast<TYPE##Decl>(D), Latest); \ + break; +#include "clang/AST/DeclNodes.inc" + } +} + +template<typename DeclT> +void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) { + D->RedeclLink.markIncomplete(); +} +void ASTDeclReader::markIncompleteDeclChainImpl(...) { + llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration"); +} + +void ASTReader::markIncompleteDeclChain(Decl *D) { + switch (D->getKind()) { +#define ABSTRACT_DECL(TYPE) +#define DECL(TYPE, BASE) \ + case Decl::TYPE: \ + ASTDeclReader::markIncompleteDeclChainImpl(cast<TYPE##Decl>(D)); \ + break; +#include "clang/AST/DeclNodes.inc" } } @@ -2374,7 +2626,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned Idx = 0; ASTDeclReader Reader(*this, *Loc.F, ID, RawLocation, Record,Idx); - Decl *D = 0; + Decl *D = nullptr; switch ((DeclCode)DeclsCursor.readRecord(Code, Record)) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: @@ -2556,7 +2808,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { break; case DECL_CXX_BASE_SPECIFIERS: Error("attempt to read a C++ base-specifier record as a declaration"); - return 0; + return nullptr; case DECL_IMPORT: // Note: last entry of the ImportDecl record is the number of stored source // locations. @@ -2595,7 +2847,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { LookupDC->setHasExternalVisibleStorage(true); if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets, Loc.F->DeclContextInfos[DC])) - return 0; + return nullptr; } // Now add the pending visible updates for this decl context, if it has any. @@ -2605,12 +2857,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // There are updates. This means the context has external visible // storage, even if the original stored version didn't. LookupDC->setHasExternalVisibleStorage(true); - DeclContextVisibleUpdates &U = I->second; - for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); - UI != UE; ++UI) { - DeclContextInfo &Info = UI->second->DeclContextInfos[DC]; + for (const auto &Update : I->second) { + DeclContextInfo &Info = Update.second->DeclContextInfos[DC]; delete Info.NameLookupTableData; - Info.NameLookupTableData = UI->first; + Info.NameLookupTableData = Update.first; } PendingVisibleUpdates.erase(I); } @@ -2618,7 +2868,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { assert(Idx == Record.size()); // Load any relevant update records. - loadDeclUpdateRecords(ID, D); + PendingUpdateRecords.push_back(std::make_pair(ID, D)); // Load the categories after recursive loading is finished. if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) @@ -2642,6 +2892,7 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); if (UpdI != DeclUpdateOffsets.end()) { FileOffsetsTy &UpdateOffsets = UpdI->second; + bool WasInteresting = isConsumerInterestedIn(D, false); for (FileOffsetsTy::iterator I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { ModuleFile *F = I->first; @@ -2654,33 +2905,23 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { unsigned RecCode = Cursor.readRecord(Code, Record); (void)RecCode; assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); - + unsigned Idx = 0; ASTDeclReader Reader(*this, *F, ID, 0, Record, Idx); Reader.UpdateDecl(D, *F, Record); + + // We might have made this declaration interesting. If so, remember that + // we need to hand it off to the consumer. + if (!WasInteresting && + isConsumerInterestedIn(D, Reader.hasPendingBody())) { + InterestingDecls.push_back(D); + WasInteresting = true; + } } } } namespace { - struct CompareLocalRedeclarationsInfoToID { - bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) { - return X.FirstID < Y; - } - - bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) { - return X < Y.FirstID; - } - - bool operator()(const LocalRedeclarationsInfo &X, - const LocalRedeclarationsInfo &Y) { - return X.FirstID < Y.FirstID; - } - bool operator()(DeclID X, DeclID Y) { - return X < Y; - } - }; - /// \brief Module visitor class that finds all of the redeclarations of a /// class RedeclChainVisitor { @@ -2724,10 +2965,11 @@ namespace { // Perform a binary search to find the local redeclarations for this // declaration (if any). + const LocalRedeclarationsInfo Compare = { ID, 0 }; const LocalRedeclarationsInfo *Result = std::lower_bound(M.RedeclarationsMap, M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, - ID, CompareLocalRedeclarationsInfoToID()); + Compare); if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap || Result->FirstID != ID) { // If we have a previously-canonical singleton declaration that was @@ -2755,6 +2997,8 @@ namespace { // Visit each of the declarations. for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) searchForID(M, SearchDecls[I]); + // FIXME: If none of the SearchDecls had local IDs in this module, can + // we avoid searching any ancestor module files? return false; } @@ -2802,24 +3046,6 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { } namespace { - struct CompareObjCCategoriesInfo { - bool operator()(const ObjCCategoriesInfo &X, DeclID Y) { - return X.DefinitionID < Y; - } - - bool operator()(DeclID X, const ObjCCategoriesInfo &Y) { - return X < Y.DefinitionID; - } - - bool operator()(const ObjCCategoriesInfo &X, - const ObjCCategoriesInfo &Y) { - return X.DefinitionID < Y.DefinitionID; - } - bool operator()(DeclID X, DeclID Y) { - return X < Y; - } - }; - /// \brief Given an ObjC interface, goes through the modules and links to the /// interface all the categories for it. class ObjCCategoriesVisitor { @@ -2878,18 +3104,15 @@ namespace { unsigned PreviousGeneration) : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface), Deserialized(Deserialized), PreviousGeneration(PreviousGeneration), - Tail(0) + Tail(nullptr) { // Populate the name -> category map with the set of known categories. - for (ObjCInterfaceDecl::known_categories_iterator - Cat = Interface->known_categories_begin(), - CatEnd = Interface->known_categories_end(); - Cat != CatEnd; ++Cat) { + for (auto *Cat : Interface->known_categories()) { if (Cat->getDeclName()) - NameCategoryMap[Cat->getDeclName()] = *Cat; + NameCategoryMap[Cat->getDeclName()] = Cat; // Keep track of the tail of the category list. - Tail = *Cat; + Tail = Cat; } } @@ -2912,10 +3135,11 @@ namespace { // Perform a binary search to find the local redeclarations for this // declaration (if any). + const ObjCCategoriesInfo Compare = { LocalID, 0 }; const ObjCCategoriesInfo *Result = std::lower_bound(M.ObjCCategoriesMap, M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap, - LocalID, CompareObjCCategoriesInfo()); + Compare); if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap || Result->DefinitionID != LocalID) { // We didn't find anything. If the class definition is in this module @@ -2946,12 +3170,14 @@ void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, const RecordData &Record) { - unsigned Idx = 0; while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { - case UPD_CXX_ADDED_IMPLICIT_MEMBER: - cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx)); + case UPD_CXX_ADDED_IMPLICIT_MEMBER: { + Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx); + assert(MD && "couldn't read decl from update record"); + cast<CXXRecordDecl>(D)->addedMember(MD); break; + } case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: // It will be added to the template's specializations set when loaded. @@ -2979,6 +3205,96 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; + case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: { + FunctionDecl *FD = cast<FunctionDecl>(D); + if (Reader.PendingBodies[FD]) { + // FIXME: Maybe check for ODR violations. + // It's safe to stop now because this update record is always last. + return; + } + + if (Record[Idx++]) { + // 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; + } + } + 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); + // Store the offset of the body so we can lazily load it later. + Reader.PendingBodies[FD] = GetCurrentCursorOffset(); + HasPendingBody = true; + assert(Idx == Record.size() && "lazy body must be last"); + break; + } + + case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { + auto *RD = cast<CXXRecordDecl>(D); + bool HadDefinition = RD->getDefinition(); + ReadCXXRecordDefinition(RD); + // Visible update is handled separately. + uint64_t LexicalOffset = Record[Idx++]; + if (!HadDefinition && LexicalOffset) { + RD->setHasExternalLexicalStorage(true); + Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor, + std::make_pair(LexicalOffset, 0), + ModuleFile.DeclContextInfos[RD]); + } + + auto TSK = (TemplateSpecializationKind)Record[Idx++]; + SourceLocation POI = Reader.ReadSourceLocation(ModuleFile, Record, Idx); + if (MemberSpecializationInfo *MSInfo = + RD->getMemberSpecializationInfo()) { + MSInfo->setTemplateSpecializationKind(TSK); + MSInfo->setPointOfInstantiation(POI); + } else { + ClassTemplateSpecializationDecl *Spec = + cast<ClassTemplateSpecializationDecl>(RD); + Spec->setTemplateSpecializationKind(TSK); + Spec->setPointOfInstantiation(POI); + + if (Record[Idx++]) { + auto PartialSpec = + ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx); + SmallVector<TemplateArgument, 8> TemplArgs; + Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); + auto *TemplArgList = TemplateArgumentList::CreateCopy( + Reader.getContext(), TemplArgs.data(), TemplArgs.size()); + Spec->setInstantiationOf(PartialSpec, TemplArgList); + } + } + + RD->setTagKind((TagTypeKind)Record[Idx++]); + RD->setLocation(Reader.ReadSourceLocation(ModuleFile, Record, Idx)); + RD->setLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx)); + RD->setRBraceLoc(Reader.ReadSourceLocation(ModuleFile, Record, Idx)); + + if (Record[Idx++]) { + AttrVec Attrs; + Reader.ReadAttributes(F, Attrs, Record, Idx); + D->setAttrsImpl(Attrs, Reader.getContext()); + } + break; + } + + case UPD_CXX_RESOLVED_EXCEPTION_SPEC: { + auto *FD = cast<FunctionDecl>(D); + auto *FPT = FD->getType()->castAs<FunctionProtoType>(); + auto EPI = FPT->getExtProtoInfo(); + SmallVector<QualType, 8> ExceptionStorage; + Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx); + FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(), + FPT->getParamTypes(), EPI)); + break; + } + case UPD_CXX_DEDUCED_RETURN_TYPE: { FunctionDecl *FD = cast<FunctionDecl>(D); Reader.Context.adjustDeducedFunctionResultType( @@ -2989,9 +3305,28 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_DECL_MARKED_USED: { // FIXME: This doesn't send the right notifications if there are // ASTMutationListeners other than an ASTWriter. - D->Used = true; + + // 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; + } break; } + + case UPD_MANGLING_NUMBER: + Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record[Idx++]); + break; + + case UPD_STATIC_LOCAL_NUMBER: + Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]); + break; } } } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h index 9149b18..a63e362 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h @@ -14,10 +14,9 @@ #define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H #include "clang/AST/DeclarationName.h" -#include "clang/Basic/OnDiskHashTable.h" #include "clang/Serialization/ASTBitCodes.h" #include "llvm/Support/Endian.h" -#include <sys/stat.h> +#include "llvm/Support/OnDiskHashTable.h" #include <utility> namespace clang { @@ -46,6 +45,8 @@ public: /// particular lookup t typedef llvm::support::ulittle32_t LE32DeclID; typedef std::pair<LE32DeclID *, LE32DeclID *> data_type; + typedef unsigned hash_value_type; + typedef unsigned offset_type; /// \brief Special internal key for declaration names. /// The hash table creates keys for comparison; we do not create @@ -67,7 +68,7 @@ public: return a.Kind == b.Kind && a.Data == b.Data; } - unsigned ComputeHash(const DeclNameKey &Key) const; + hash_value_type ComputeHash(const DeclNameKey &Key) const; internal_key_type GetInternalKey(const external_key_type& Name) const; static std::pair<unsigned, unsigned> @@ -92,13 +93,14 @@ class ASTIdentifierLookupTraitBase { public: typedef StringRef external_key_type; typedef StringRef internal_key_type; - + typedef unsigned hash_value_type; + typedef unsigned offset_type; static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { return a == b; } - static unsigned ComputeHash(const internal_key_type& a); + static hash_value_type ComputeHash(const internal_key_type& a); static std::pair<unsigned, unsigned> ReadKeyDataLength(const unsigned char*& d); @@ -126,11 +128,11 @@ class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase { public: typedef IdentifierInfo * data_type; - + ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F, - IdentifierInfo *II = 0) + IdentifierInfo *II = nullptr) : Reader(Reader), F(F), KnownII(II) { } - + data_type ReadData(const internal_key_type& k, const unsigned char* d, unsigned DataLen); @@ -140,7 +142,7 @@ public: /// \brief The on-disk hash table used to contain information about /// all of the identifiers in the program. -typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait> +typedef llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait> ASTIdentifierLookupTable; /// \brief Class that performs lookup for a selector's entries in the global @@ -160,6 +162,8 @@ public: typedef Selector external_key_type; typedef external_key_type internal_key_type; + typedef unsigned hash_value_type; + typedef unsigned offset_type; ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F) : Reader(Reader), F(F) { } @@ -169,7 +173,7 @@ public: return a == b; } - static unsigned ComputeHash(Selector Sel); + static hash_value_type ComputeHash(Selector Sel); static const internal_key_type& GetInternalKey(const external_key_type& x) { return x; } @@ -182,7 +186,7 @@ public: }; /// \brief The on-disk hash table used for the global method pool. -typedef OnDiskChainedHashTable<ASTSelectorLookupTrait> +typedef llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait> ASTSelectorLookupTable; /// \brief Trait class used to search the on-disk hash table containing all of @@ -211,12 +215,14 @@ public: typedef const internal_key_type &internal_key_ref; typedef HeaderFileInfo data_type; + typedef unsigned hash_value_type; + typedef unsigned offset_type; HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS, const char *FrameworkStrings) : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) { } - static unsigned ComputeHash(internal_key_ref ikey); + static hash_value_type ComputeHash(internal_key_ref ikey); static internal_key_type GetInternalKey(const FileEntry *FE); bool EqualKey(internal_key_ref a, internal_key_ref b); @@ -229,7 +235,7 @@ public: }; /// \brief The on-disk hash table used for known header files. -typedef OnDiskChainedHashTable<HeaderFileInfoTrait> +typedef llvm::OnDiskChainedHashTable<HeaderFileInfoTrait> HeaderFileInfoLookupTable; } // end namespace clang::serialization::reader diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp index 1115e8f..8bf17d5 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp @@ -176,7 +176,7 @@ void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { (void)NumAttrs; assert(NumAttrs == S->NumAttrs); assert(NumAttrs == Attrs.size()); - std::copy(Attrs.begin(), Attrs.end(), S->Attrs); + std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr()); S->SubStmt = Reader.ReadSubStmt(); S->AttrLoc = ReadSourceLocation(Record, Idx); } @@ -202,7 +202,7 @@ void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) { if (Record[Idx++]) S->setAllEnumCasesCovered(); - SwitchCase *PrevSC = 0; + SwitchCase *PrevSC = nullptr; for (unsigned N = Record.size(); Idx != N; ++Idx) { SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]); if (PrevSC) @@ -399,13 +399,11 @@ void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { S->getCapturedDecl()->setBody(S->getCapturedStmt()); // Captures - for (CapturedStmt::capture_iterator I = S->capture_begin(), - E = S->capture_end(); - I != E; ++I) { - I->VarAndKind.setPointer(ReadDeclAs<VarDecl>(Record, Idx)); - I->VarAndKind + for (auto &I : S->captures()) { + I.VarAndKind.setPointer(ReadDeclAs<VarDecl>(Record, Idx)); + I.VarAndKind .setInt(static_cast<CapturedStmt::VariableCaptureKind>(Record[Idx++])); - I->Loc = ReadSourceLocation(Record, Idx); + I.Loc = ReadSourceLocation(Record, Idx); } } @@ -718,7 +716,7 @@ void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { E->setLBraceLoc(ReadSourceLocation(Record, Idx)); E->setRBraceLoc(ReadSourceLocation(Record, Idx)); bool isArrayFiller = Record[Idx++]; - Expr *filler = 0; + Expr *filler = nullptr; if (isArrayFiller) { filler = Reader.ReadSubExpr(); E->ArrayFillerOrUnionFieldInit = filler; @@ -1198,6 +1196,7 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->setElidable(Record[Idx++]); E->setHadMultipleCandidates(Record[Idx++]); E->setListInitialization(Record[Idx++]); + E->setStdInitListInitialization(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); E->ParenOrBraceRange = ReadSourceRange(Record, Idx); @@ -1484,33 +1483,15 @@ void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { E->NamingClass = ReadDeclAs<CXXRecordDecl>(Record, Idx); } -void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - VisitExpr(E); - E->UTT = (UnaryTypeTrait)Record[Idx++]; - E->Value = (bool)Record[Idx++]; - SourceRange Range = ReadSourceRange(Record, Idx); - E->Loc = Range.getBegin(); - E->RParen = Range.getEnd(); - E->QueriedType = GetTypeSourceInfo(Record, Idx); -} - -void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { - VisitExpr(E); - E->BTT = (BinaryTypeTrait)Record[Idx++]; - E->Value = (bool)Record[Idx++]; - SourceRange Range = ReadSourceRange(Record, Idx); - E->Loc = Range.getBegin(); - E->RParen = Range.getEnd(); - E->LhsType = GetTypeSourceInfo(Record, Idx); - E->RhsType = GetTypeSourceInfo(Record, Idx); -} - void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { VisitExpr(E); E->TypeTraitExprBits.NumArgs = Record[Idx++]; E->TypeTraitExprBits.Kind = Record[Idx++]; E->TypeTraitExprBits.Value = Record[Idx++]; - + SourceRange Range = ReadSourceRange(Record, Idx); + E->Loc = Range.getBegin(); + E->RParenLoc = Range.getEnd(); + TypeSourceInfo **Args = E->getTypeSourceInfos(); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) Args[I] = GetTypeSourceInfo(Record, Idx); @@ -1592,8 +1573,10 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); - E->Temporary = Reader.ReadSubExpr(); - E->ExtendingDecl = ReadDeclAs<ValueDecl>(Record, Idx); + E->State = Reader.ReadSubExpr(); + auto VD = ReadDeclAs<ValueDecl>(Record, Idx); + unsigned ManglingNumber = Record[Idx++]; + E->setExtendingDecl(VD, ManglingNumber); } void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { @@ -1627,6 +1610,11 @@ void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { E->setExprOperand(Reader.ReadSubExpr()); } +void ASTStmtReader::VisitSEHLeaveStmt(SEHLeaveStmt *S) { + VisitStmt(S); + S->setLeaveLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitSEHExceptStmt(SEHExceptStmt *S) { VisitStmt(S); S->Loc = ReadSourceLocation(Record, Idx); @@ -1691,18 +1679,72 @@ public: OMPClause *OMPClauseReader::readClause() { OMPClause *C; switch (Record[Idx++]) { + case OMPC_if: + C = new (Context) OMPIfClause(); + break; + case OMPC_final: + C = new (Context) OMPFinalClause(); + break; + case OMPC_num_threads: + C = new (Context) OMPNumThreadsClause(); + break; + case OMPC_safelen: + C = new (Context) OMPSafelenClause(); + break; + case OMPC_collapse: + C = new (Context) OMPCollapseClause(); + break; case OMPC_default: C = new (Context) OMPDefaultClause(); break; + case OMPC_proc_bind: + C = new (Context) OMPProcBindClause(); + break; + case OMPC_schedule: + C = new (Context) OMPScheduleClause(); + break; + case OMPC_ordered: + C = new (Context) OMPOrderedClause(); + break; + case OMPC_nowait: + C = new (Context) OMPNowaitClause(); + break; + case OMPC_untied: + C = new (Context) OMPUntiedClause(); + break; + case OMPC_mergeable: + C = new (Context) OMPMergeableClause(); + break; case OMPC_private: C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]); break; case OMPC_firstprivate: C = OMPFirstprivateClause::CreateEmpty(Context, Record[Idx++]); break; + case OMPC_lastprivate: + C = OMPLastprivateClause::CreateEmpty(Context, Record[Idx++]); + break; case OMPC_shared: C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]); break; + case OMPC_reduction: + C = OMPReductionClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_linear: + C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_aligned: + C = OMPAlignedClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_copyin: + C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_copyprivate: + C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_flush: + C = OMPFlushClause::CreateEmpty(Context, Record[Idx++]); + break; } Visit(C); C->setLocStart(Reader->ReadSourceLocation(Record, Idx)); @@ -1711,6 +1753,31 @@ OMPClause *OMPClauseReader::readClause() { return C; } +void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) { + C->setCondition(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) { + C->setCondition(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + C->setNumThreads(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) { + C->setSafelen(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) { + C->setNumForLoops(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} + void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { C->setDefaultKind( static_cast<OpenMPDefaultClauseKind>(Record[Idx++])); @@ -1718,6 +1785,30 @@ void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx)); } +void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) { + C->setProcBindKind( + static_cast<OpenMPProcBindClauseKind>(Record[Idx++])); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setProcBindKindKwLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) { + C->setScheduleKind( + static_cast<OpenMPScheduleClauseKind>(Record[Idx++])); + C->setChunkSize(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *) {} + +void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {} + +void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {} + +void OMPClauseReader::VisitOMPMergeableClause(OMPMergeableClause *) {} + void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); @@ -1738,6 +1829,16 @@ void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { C->setVarRefs(Vars); } +void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); @@ -1748,12 +1849,82 @@ void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) { C->setVarRefs(Vars); } +void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setColonLoc(Reader->ReadSourceLocation(Record, Idx)); + NestedNameSpecifierLoc NNSL = + Reader->Reader.ReadNestedNameSpecifierLoc(Reader->F, Record, Idx); + DeclarationNameInfo DNI; + Reader->ReadDeclarationNameInfo(DNI, Record, Idx); + C->setQualifierLoc(NNSL); + C->setNameInfo(DNI); + + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + +void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setColonLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); + C->setStep(Reader->Reader.ReadSubExpr()); +} + +void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setColonLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); + C->setAlignment(Reader->Reader.ReadSubExpr()); +} + +void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + +void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + +void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + //===----------------------------------------------------------------------===// // OpenMP Directives. //===----------------------------------------------------------------------===// void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { - VisitStmt(E); - ++Idx; E->setLocStart(ReadSourceLocation(Record, Idx)); E->setLocEnd(ReadSourceLocation(Record, Idx)); OMPClauseReader ClauseReader(this, Reader.getContext(), Record, Idx); @@ -1761,10 +1932,102 @@ void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { for (unsigned i = 0; i < E->getNumClauses(); ++i) Clauses.push_back(ClauseReader.readClause()); E->setClauses(Clauses); - E->setAssociatedStmt(Reader.ReadSubStmt()); + if (E->hasAssociatedStmt()) + E->setAssociatedStmt(Reader.ReadSubStmt()); } void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) { + VisitStmt(D); + // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. + Idx += 2; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) { + VisitStmt(D); + // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. + Idx += 2; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + ReadDeclarationNameInfo(D->DirName, Record, Idx); +} + +void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { + VisitStmt(D); + // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. + Idx += 2; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPParallelSectionsDirective( + OMPParallelSectionsDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPBarrierDirective(OMPBarrierDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + +void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; VisitOMPExecutableDirective(D); } @@ -1826,7 +2089,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: Error("malformed block record in AST file"); - return 0; + return nullptr; case llvm::BitstreamEntry::EndBlock: goto Done; case llvm::BitstreamEntry::Record: @@ -1834,8 +2097,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } - - Stmt *S = 0; + Stmt *S = nullptr; Idx = 0; Record.clear(); bool Finished = false; @@ -1853,7 +2115,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case STMT_NULL_PTR: - S = 0; + S = nullptr; break; case STMT_NULL: @@ -2044,7 +2306,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc, TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, - HasTemplateKWAndArgsInfo ? &ArgInfo : 0, + HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T, VK, OK); ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc, MemberD->getDeclName(), Record, Idx); @@ -2212,6 +2474,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_OBJC_BOOL_LITERAL: S = new (Context) ObjCBoolLiteralExpr(Empty); break; + case STMT_SEH_LEAVE: + S = new (Context) SEHLeaveStmt(Empty); + break; case STMT_SEH_EXCEPT: S = new (Context) SEHExceptStmt(Empty); break; @@ -2238,15 +2503,89 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) MSDependentExistsStmt(SourceLocation(), true, NestedNameSpecifierLoc(), DeclarationNameInfo(), - 0); + nullptr); break; + case STMT_OMP_PARALLEL_DIRECTIVE: S = OMPParallelDirective::CreateEmpty(Context, Record[ASTStmtReader::NumStmtFields], Empty); break; - + + case STMT_OMP_SIMD_DIRECTIVE: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPSimdDirective::CreateEmpty(Context, NumClauses, + CollapsedNum, Empty); + break; + } + + case STMT_OMP_FOR_DIRECTIVE: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPForDirective::CreateEmpty(Context, NumClauses, CollapsedNum, + Empty); + break; + } + + case STMT_OMP_SECTIONS_DIRECTIVE: + S = OMPSectionsDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + + case STMT_OMP_SECTION_DIRECTIVE: + S = OMPSectionDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_SINGLE_DIRECTIVE: + S = OMPSingleDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + + case STMT_OMP_MASTER_DIRECTIVE: + S = OMPMasterDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_CRITICAL_DIRECTIVE: + S = OMPCriticalDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_PARALLEL_FOR_DIRECTIVE: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPParallelForDirective::CreateEmpty(Context, NumClauses, + CollapsedNum, Empty); + break; + } + + case STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE: + S = OMPParallelSectionsDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + + case STMT_OMP_TASK_DIRECTIVE: + S = OMPTaskDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + + case STMT_OMP_TASKYIELD_DIRECTIVE: + S = OMPTaskyieldDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_BARRIER_DIRECTIVE: + S = OMPBarrierDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_TASKWAIT_DIRECTIVE: + S = OMPTaskwaitDirective::CreateEmpty(Context, Empty); + break; + + case STMT_OMP_FLUSH_DIRECTIVE: + S = OMPFlushDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; @@ -2254,11 +2593,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_CXX_MEMBER_CALL: S = new (Context) CXXMemberCallExpr(Context, Empty); break; - + case EXPR_CXX_CONSTRUCT: S = new (Context) CXXConstructExpr(Empty); break; - + case EXPR_CXX_TEMPORARY_OBJECT: S = new (Context) CXXTemporaryObjectExpr(Empty); break; @@ -2327,7 +2666,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields]; if (HasOtherExprStored) { Expr *SubExpr = ReadSubExpr(); - S = CXXDefaultArgExpr::Create(Context, SourceLocation(), 0, SubExpr); + S = CXXDefaultArgExpr::Create(Context, SourceLocation(), nullptr, + SubExpr); } else S = new (Context) CXXDefaultArgExpr(Empty); break; @@ -2393,14 +2733,6 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { ? Record[ASTStmtReader::NumExprFields + 1] : 0); break; - - case EXPR_CXX_UNARY_TYPE_TRAIT: - S = new (Context) UnaryTypeTraitExpr(Empty); - break; - - case EXPR_BINARY_TYPE_TRAIT: - S = new (Context) BinaryTypeTraitExpr(Empty); - break; case EXPR_TYPE_TRAIT: S = TypeTraitExpr::CreateDeserialized(Context, @@ -2491,7 +2823,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { StmtStack.push_back(S); } Done: - assert(StmtStack.size() > PrevNumStmts && "Read too many sub stmts!"); + assert(StmtStack.size() > PrevNumStmts && "Read too many sub-stmts!"); assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!"); return StmtStack.pop_back_val(); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 405488c..0f52a9f 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -17,14 +17,15 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclLookups.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemStatCache.h" -#include "clang/Basic/OnDiskHashTable.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/TargetInfo.h" @@ -45,8 +46,10 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include <algorithm> #include <cstdio> @@ -113,6 +116,12 @@ void ASTTypeWriter::VisitDecayedType(const DecayedType *T) { Code = TYPE_DECAYED; } +void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) { + Writer.AddTypeRef(T->getOriginalType(), Record); + Writer.AddTypeRef(T->getAdjustedType(), Record); + Code = TYPE_ADJUSTED; +} + void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { Writer.AddTypeRef(T->getPointeeType(), Record); Code = TYPE_BLOCK_POINTER; @@ -173,7 +182,7 @@ void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) { } void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { - Writer.AddTypeRef(T->getResultType(), Record); + Writer.AddTypeRef(T->getReturnType(), Record); FunctionType::ExtInfo C = T->getExtInfo(); Record.push_back(C.getNoReturn()); Record.push_back(C.getHasRegParm()); @@ -188,15 +197,8 @@ void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { Code = TYPE_FUNCTION_NO_PROTO; } -void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { - VisitFunctionType(T); - Record.push_back(T->getNumArgs()); - for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I) - Writer.AddTypeRef(T->getArgType(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())); +static void addExceptionSpec(ASTWriter &Writer, const FunctionProtoType *T, + ASTWriter::RecordDataImpl &Record) { Record.push_back(T->getExceptionSpecType()); if (T->getExceptionSpecType() == EST_Dynamic) { Record.push_back(T->getNumExceptions()); @@ -210,6 +212,18 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { } else if (T->getExceptionSpecType() == EST_Unevaluated) { Writer.AddDeclRef(T->getExceptionSpecDecl(), Record); } +} + +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); Code = TYPE_FUNCTION_PROTO; } @@ -395,9 +409,8 @@ void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { Writer.AddTypeRef(T->getBaseType(), Record); Record.push_back(T->getNumProtocols()); - for (ObjCObjectType::qual_iterator I = T->qual_begin(), - E = T->qual_end(); I != E; ++I) - Writer.AddDeclRef(*I, Record); + for (const auto *I : T->quals()) + Writer.AddDeclRef(I, Record); Code = TYPE_OBJC_OBJECT; } @@ -455,6 +468,9 @@ void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) { void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) { // nothing to do } +void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { + // nothing to do +} void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { Writer.AddSourceLocation(TL.getCaretLoc(), Record); } @@ -503,8 +519,8 @@ void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { Writer.AddSourceLocation(TL.getLParenLoc(), Record); Writer.AddSourceLocation(TL.getRParenLoc(), Record); Writer.AddSourceLocation(TL.getLocalRangeEnd(), Record); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Writer.AddDeclRef(TL.getArg(i), Record); + for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) + Writer.AddDeclRef(TL.getParam(i), Record); } void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { VisitFunctionTypeLoc(TL); @@ -645,7 +661,8 @@ static void EmitBlockID(unsigned ID, const char *Name, Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); // Emit the block name if present. - if (Name == 0 || Name[0] == 0) return; + if (!Name || Name[0] == 0) + return; Record.clear(); while (*Name) Record.push_back(*Name++); @@ -764,10 +781,8 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT); RECORD(EXPR_CXX_UNRESOLVED_MEMBER); RECORD(EXPR_CXX_UNRESOLVED_LOOKUP); - RECORD(EXPR_CXX_UNARY_TYPE_TRAIT); RECORD(EXPR_CXX_NOEXCEPT); RECORD(EXPR_OPAQUE_VALUE); - RECORD(EXPR_BINARY_TYPE_TRAIT); RECORD(EXPR_PACK_EXPANSION); RECORD(EXPR_SIZEOF_PACK); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); @@ -785,6 +800,8 @@ void ASTWriter::WriteBlockInfoBlock() { // Control Block. BLOCK(CONTROL_BLOCK); RECORD(METADATA); + RECORD(MODULE_NAME); + RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); RECORD(LANGUAGE_OPTIONS); RECORD(TARGET_OPTIONS); @@ -806,7 +823,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_OFFSET); RECORD(IDENTIFIER_OFFSET); RECORD(IDENTIFIER_TABLE); - RECORD(EXTERNAL_DEFINITIONS); + RECORD(EAGERLY_DESERIALIZED_DECLS); RECORD(SPECIAL_TYPES); RECORD(STATISTICS); RECORD(TENTATIVE_DEFINITIONS); @@ -849,6 +866,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MACRO_OFFSET); RECORD(MACRO_TABLE); RECORD(LATE_PARSED_TEMPLATE); + RECORD(OPTIMIZE_PRAGMA_OPTIONS); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -1037,10 +1055,35 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); + // Module name + if (WritingModule) { + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); + RecordData Record; + Record.push_back(MODULE_NAME); + Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name); + } + + // Module map file + if (WritingModule) { + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MODULE_MAP_FILE)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename + 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()); + } + // Imports if (Chain) { serialization::ModuleManager &Mgr = Chain->getModuleManager(); - SmallVector<char, 128> ModulePaths; Record.clear(); for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end(); @@ -1053,7 +1096,6 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, AddSourceLocation((*M)->ImportLoc, Record); Record.push_back((*M)->File->getSize()); Record.push_back((*M)->File->getModificationTime()); - // FIXME: This writes the absolute path for AST files we depend on. const std::string &FileName = (*M)->FileName; Record.push_back(FileName.size()); Record.append(FileName.begin(), FileName.end()); @@ -1097,8 +1139,6 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, AddString(TargetOpts.Triple, Record); AddString(TargetOpts.CPU, Record); AddString(TargetOpts.ABI, Record); - AddString(TargetOpts.CXXABI, Record); - AddString(TargetOpts.LinkerVersion, Record); Record.push_back(TargetOpts.FeaturesAsWritten.size()); for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) { AddString(TargetOpts.FeaturesAsWritten[I], Record); @@ -1120,6 +1160,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back(DiagOpts.Warnings.size()); for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I) AddString(DiagOpts.Warnings[I], Record); + Record.push_back(DiagOpts.Remarks.size()); + for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I) + AddString(DiagOpts.Remarks[I], Record); // Note: we don't serialize the log or serialization file names, because they // are generally transient files and will almost always be overridden. Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); @@ -1156,6 +1199,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, AddString(HSOpts.ResourceDir, Record); AddString(HSOpts.ModuleCachePath, Record); + AddString(HSOpts.ModuleUserBuildPath, Record); Record.push_back(HSOpts.DisableModuleHash); Record.push_back(HSOpts.UseBuiltinIncludes); Record.push_back(HSOpts.UseStandardSystemIncludes); @@ -1294,33 +1338,6 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, SortedFiles.push_front(Entry); } - // If we have an isysroot for a Darwin SDK, include its SDKSettings.plist in - // the set of (non-system) input files. This is simple heuristic for - // detecting whether the system headers may have changed, because it is too - // expensive to stat() all of the system headers. - FileManager &FileMgr = SourceMgr.getFileManager(); - if (!HSOpts.Sysroot.empty() && !Chain) { - llvm::SmallString<128> SDKSettingsFileName(HSOpts.Sysroot); - llvm::sys::path::append(SDKSettingsFileName, "SDKSettings.plist"); - if (const FileEntry *SDKSettingsFile = FileMgr.getFile(SDKSettingsFileName)) { - InputFileEntry Entry = { SDKSettingsFile, false, false }; - SortedFiles.push_front(Entry); - } - } - - // Add the compiler's own module.map in the set of (non-system) input files. - // This is a simple heuristic for detecting whether the compiler's headers - // have changed, because we don't want to stat() all of them. - if (Modules && !Chain) { - SmallString<128> P = StringRef(HSOpts.ResourceDir); - llvm::sys::path::append(P, "include"); - llvm::sys::path::append(P, "module.map"); - if (const FileEntry *ModuleMapFile = FileMgr.getFile(P)) { - InputFileEntry Entry = { ModuleMapFile, false, false }; - SortedFiles.push_front(Entry); - } - } - unsigned UserFilesNum = 0; // Write out all of the input files. std::vector<uint32_t> InputFileOffsets; @@ -1357,7 +1374,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, // Ask the file manager to fixup the relative path for us. This will // honor the working directory. - FileMgr.FixupRelativePath(FilePath); + SourceMgr.getFileManager().FixupRelativePath(FilePath); // FIXME: This call to make_absolute shouldn't be necessary, the // call to FixupRelativePath should always return an absolute path. @@ -1470,8 +1487,10 @@ namespace { typedef HeaderFileInfo data_type; typedef const data_type &data_type_ref; + typedef unsigned hash_value_type; + typedef unsigned offset_type; - static unsigned ComputeHash(key_type_ref key) { + static hash_value_type ComputeHash(key_type_ref key) { // 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. @@ -1481,26 +1500,31 @@ namespace { std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { + using namespace llvm::support; + endian::Writer<little> Writer(Out); unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8; - clang::io::Emit16(Out, KeyLen); + Writer.write<uint16_t>(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; if (Data.isModuleHeader) DataLen += 4; - clang::io::Emit8(Out, DataLen); + Writer.write<uint8_t>(DataLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { - clang::io::Emit64(Out, key.FE->getSize()); + using namespace llvm::support; + endian::Writer<little> LE(Out); + LE.write<uint64_t>(key.FE->getSize()); KeyLen -= 8; - clang::io::Emit64(Out, key.FE->getModificationTime()); + LE.write<uint64_t>(key.FE->getModificationTime()); KeyLen -= 8; Out.write(key.Filename, KeyLen); } void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { - using namespace clang::io; + using namespace llvm::support; + endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; unsigned char Flags = (Data.HeaderRole << 6) @@ -1509,13 +1533,13 @@ namespace { | (Data.DirInfo << 2) | (Data.Resolved << 1) | Data.IndexHeaderMapHeader; - Emit8(Out, (uint8_t)Flags); - Emit16(Out, (uint16_t) Data.NumIncludes); + LE.write<uint8_t>(Flags); + LE.write<uint16_t>(Data.NumIncludes); if (!Data.ControllingMacro) - Emit32(Out, (uint32_t)Data.ControllingMacroID); + LE.write<uint32_t>(Data.ControllingMacroID); else - Emit32(Out, (uint32_t)Writer.getIdentifierRef(Data.ControllingMacro)); + LE.write<uint32_t>(Writer.getIdentifierRef(Data.ControllingMacro)); unsigned Offset = 0; if (!Data.Framework.empty()) { @@ -1532,11 +1556,11 @@ namespace { } else Offset = Pos->second; } - Emit32(Out, Offset); + LE.write<uint32_t>(Offset); if (Data.isModuleHeader) { Module *Mod = HS.findModuleForHeader(key.FE).getModule(); - Emit32(Out, Writer.getExistingSubmoduleID(Mod)); + LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod)); } assert(Out.tell() - Start == DataLen && "Wrong data length"); @@ -1558,7 +1582,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { FilesByUID.resize(HS.header_file_size()); HeaderFileInfoTrait GeneratorTrait(*this, HS); - OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; + llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; SmallVector<const char *, 4> SavedStrings; unsigned NumHeaderSearchEntries = 0; for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { @@ -1568,10 +1592,10 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo // from the external source if it was not provided already. - const HeaderFileInfo &HFI = HS.getFileInfo(File); - if (HFI.External && Chain) - continue; - if (HFI.isModuleHeader && !HFI.isCompilingModuleHeader) + HeaderFileInfo HFI; + if (!HS.tryGetFileInfo(File, HFI) || + (HFI.External && Chain) || + (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)) continue; // Turn the file name into an absolute path, if it isn't already. @@ -1594,9 +1618,10 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { SmallString<4096> TableData; uint32_t BucketOffset; { + using namespace llvm::support; llvm::raw_svector_ostream Out(TableData); // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); + endian::Writer<little>(Out).write<uint32_t>(0); BucketOffset = Generator.Emit(Out, GeneratorTrait); } @@ -1837,8 +1862,10 @@ public: typedef Data data_type; typedef const data_type &data_type_ref; + typedef unsigned hash_value_type; + typedef unsigned offset_type; - static unsigned ComputeHash(IdentID IdID) { + static hash_value_type ComputeHash(IdentID IdID) { return llvm::hash_value(IdID); } @@ -1851,12 +1878,14 @@ public: } static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { - clang::io::Emit32(Out, Key); + using namespace llvm::support; + endian::Writer<little>(Out).write<uint32_t>(Key); } static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, unsigned) { - clang::io::Emit32(Out, Data.MacroDirectivesOffset); + using namespace llvm::support; + endian::Writer<little>(Out).write<uint32_t>(Data.MacroDirectivesOffset); } }; } // end anonymous namespace @@ -1874,6 +1903,12 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, return true; 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; + SourceLocation Loc = MD->getLocation(); if (Loc.isInvalid()) return true; @@ -1928,7 +1963,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), &compareMacroDirectives); - OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator; + llvm::OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator; // Emit the macro directives as a list and associate the offset with the // identifier they belong to. @@ -1946,8 +1981,6 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // Emit the macro directives in reverse source order. for (; MD; MD = MD->getPrevious()) { - if (MD->isHidden()) - continue; if (shouldIgnoreMacro(MD, IsModule, PP)) continue; @@ -2012,6 +2045,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { AddSourceLocation(MI->getDefinitionLoc(), Record); AddSourceLocation(MI->getDefinitionEndLoc(), Record); Record.push_back(MI->isUsed()); + Record.push_back(MI->isUsedForHeaderGuard()); unsigned Code; if (MI->isObjectLike()) { Code = PP_MACRO_OBJECT_LIKE; @@ -2054,9 +2088,10 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { SmallString<4096> MacroTable; uint32_t BucketOffset; { + using namespace llvm::support; llvm::raw_svector_ostream Out(MacroTable); // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); + endian::Writer<little>(Out).write<uint32_t>(0); BucketOffset = Generator.Emit(Out); } @@ -2227,9 +2262,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { // other consumers of this information. SourceManager &SrcMgr = PP->getSourceManager(); ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); - for (ASTContext::import_iterator I = Context->local_import_begin(), - IEnd = Context->local_import_end(); - I != IEnd; ++I) { + for (const auto *I : Context->local_imports()) { if (Module *ImportedFrom = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(), SrcMgr))) { @@ -2248,7 +2281,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... @@ -2336,6 +2370,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Record.push_back(Mod->IsFramework); Record.push_back(Mod->IsExplicit); Record.push_back(Mod->IsSystem); + Record.push_back(Mod->IsExternC); Record.push_back(Mod->InferSubmodules); Record.push_back(Mod->InferExplicitSubmodules); Record.push_back(Mod->InferExportWildcard); @@ -2516,7 +2551,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, I = point.State->begin(), E = point.State->end(); I != E; ++I) { if (I->second.isPragma()) { Record.push_back(I->first); - Record.push_back(I->second.getMapping()); + Record.push_back((unsigned)I->second.getSeverity()); } } Record.push_back(-1); // mark the end of the diag/map pairs for this @@ -2618,9 +2653,8 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, RecordData Record; Record.push_back(DECL_CONTEXT_LEXICAL); SmallVector<KindDeclIDPair, 64> Decls; - for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); - D != DEnd; ++D) - Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D))); + for (const auto *D : DC->decls()) + Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D))); ++NumLexicalDeclContexts; Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls)); @@ -2719,17 +2753,22 @@ public: }; typedef const data_type& data_type_ref; + typedef unsigned hash_value_type; + typedef unsigned offset_type; + explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) { } - static unsigned ComputeHash(Selector Sel) { + static hash_value_type ComputeHash(Selector Sel) { return serialization::ComputeHash(Sel); } std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, Selector Sel, data_type_ref Methods) { + using namespace llvm::support; + endian::Writer<little> LE(Out); unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); - clang::io::Emit16(Out, KeyLen); + LE.write<uint16_t>(KeyLen); unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) @@ -2739,27 +2778,31 @@ public: Method = Method->getNext()) if (Method->Method) DataLen += 4; - clang::io::Emit16(Out, DataLen); + LE.write<uint16_t>(DataLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream& Out, Selector Sel, unsigned) { + using namespace llvm::support; + endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); assert((Start >> 32) == 0 && "Selector key offset too large"); Writer.SetSelectorOffset(Sel, Start); unsigned N = Sel.getNumArgs(); - clang::io::Emit16(Out, N); + LE.write<uint16_t>(N); if (N == 0) N = 1; for (unsigned I = 0; I != N; ++I) - clang::io::Emit32(Out, - Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); + LE.write<uint32_t>( + Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); } void EmitData(raw_ostream& Out, key_type_ref, data_type_ref Methods, unsigned DataLen) { + using namespace llvm::support; + endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; - clang::io::Emit32(Out, Methods.ID); + LE.write<uint32_t>(Methods.ID); unsigned NumInstanceMethods = 0; for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) @@ -2779,16 +2822,16 @@ public: unsigned FactoryBits = Methods.Factory.getBits(); assert(FactoryBits < 4); unsigned NumFactoryMethodsAndBits = (NumFactoryMethods << 2) | FactoryBits; - clang::io::Emit16(Out, NumInstanceMethodsAndBits); - clang::io::Emit16(Out, NumFactoryMethodsAndBits); + LE.write<uint16_t>(NumInstanceMethodsAndBits); + LE.write<uint16_t>(NumFactoryMethodsAndBits); for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (Method->Method) - clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); + LE.write<uint32_t>(Writer.getDeclID(Method->Method)); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (Method->Method) - clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); + LE.write<uint32_t>(Writer.getDeclID(Method->Method)); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -2809,7 +2852,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { unsigned NumTableEntries = 0; // Create and write out the blob that contains selectors and the method pool. { - OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator; + llvm::OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator; ASTMethodPoolTrait Trait(*this); // Create the on-disk hash table representation. We walk through every @@ -2857,10 +2900,11 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { SmallString<4096> MethodPool; uint32_t BucketOffset; { + using namespace llvm::support; ASTMethodPoolTrait Trait(*this); llvm::raw_svector_ostream Out(MethodPool); // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); + endian::Writer<little>(Out).write<uint32_t>(0); BucketOffset = Generator.Emit(Out, Trait); } @@ -2959,83 +3003,110 @@ class ASTIdentifierTableTrait { return false; } - DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD, - SubmoduleID &ModID) { + typedef llvm::SmallVectorImpl<SubmoduleID> OverriddenList; + + MacroDirective * + getFirstPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID) { ModID = 0; - if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID)) - if (!shouldIgnoreMacro(DefMD, IsModule, PP)) - return DefMD; - return 0; + llvm::SmallVector<SubmoduleID, 1> Overridden; + if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden)) + if (!shouldIgnoreMacro(NextMD, IsModule, PP)) + return NextMD; + return nullptr; } - DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD, - SubmoduleID &ModID) { - if (DefMacroDirective * - DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID)) - if (!shouldIgnoreMacro(DefMD, IsModule, PP)) - return DefMD; - return 0; + MacroDirective * + getNextPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID, + OverriddenList &Overridden) { + if (MacroDirective *NextMD = + getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden)) + if (!shouldIgnoreMacro(NextMD, IsModule, PP)) + return NextMD; + return nullptr; } /// \brief Traverses the macro directives history and returns the latest - /// macro that is public and not undefined in the same submodule. - /// A macro that is defined in submodule A and undefined in submodule B, + /// public macro definition or undefinition that is not in ModID. + /// A macro that is defined in submodule A and undefined in submodule B /// will still be considered as defined/exported from submodule A. - DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD, - SubmoduleID &ModID) { + /// 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(); if (!MD) - return 0; + return nullptr; SubmoduleID OrigModID = ModID; - bool isUndefined = false; - Optional<bool> isPublic; + Optional<bool> IsPublic; for (; MD; MD = MD->getPrevious()) { - if (MD->isHidden()) - continue; - SubmoduleID ThisModID = getSubmoduleID(MD); if (ThisModID == 0) { - isUndefined = false; - isPublic = Optional<bool>(); + 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! + continue; } - if (ThisModID != ModID){ + if (ThisModID != ModID) { ModID = ThisModID; - isUndefined = false; - isPublic = Optional<bool>(); + IsPublic = Optional<bool>(); } + + // 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 (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; - if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { - if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue())) - return DefMD; - continue; - } - - if (isa<UndefMacroDirective>(MD)) { - isUndefined = true; - 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; } - - VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD); - if (!isPublic.hasValue()) - isPublic = VisMD->isPublic(); } - return 0; + return nullptr; } SubmoduleID getSubmoduleID(MacroDirective *MD) { - if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { - MacroInfo *MI = DefMD->getInfo(); - if (unsigned ID = MI->getOwningModuleID()) - return ID; - return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc()); - } return Writer.inferSubmoduleIDFromLocation(MD->getLocation()); } @@ -3046,11 +3117,14 @@ public: typedef IdentID data_type; typedef data_type data_type_ref; + typedef unsigned hash_value_type; + typedef unsigned offset_type; + ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule) : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { } - static unsigned ComputeHash(const IdentifierInfo* II) { + static hash_value_type ComputeHash(const IdentifierInfo* II) { return llvm::HashString(II->getName()); } @@ -3058,7 +3132,7 @@ public: EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - MacroDirective *Macro = 0; + MacroDirective *Macro = nullptr; if (isInterestingIdentifier(II, Macro)) { DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags @@ -3066,11 +3140,18 @@ public: DataLen += 4; // MacroDirectives offset. if (IsModule) { SubmoduleID ModID; - for (DefMacroDirective * - DefMD = getFirstPublicSubmoduleMacro(Macro, ModID); - DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) { - DataLen += 4; // MacroInfo ID. + 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()); + DataLen += 4; // MacroInfo ID or ModuleID. } + // Previous macro's overrides. + if (!Overridden.empty()) + DataLen += 4 * (1 + Overridden.size()); DataLen += 4; } } @@ -3080,11 +3161,14 @@ public: D != DEnd; ++D) DataLen += sizeof(DeclID); } - clang::io::Emit16(Out, DataLen); + using namespace llvm::support; + endian::Writer<little> LE(Out); + + LE.write<uint16_t>(DataLen); // We emit the key length after the data length so that every // string is preceded by a 16-bit length. This matches the PTH // format for storing identifiers. - clang::io::Emit16(Out, KeyLen); + LE.write<uint16_t>(KeyLen); return std::make_pair(KeyLen, DataLen); } @@ -3096,18 +3180,31 @@ public: Out.write(II->getNameStart(), KeyLen); } + static void emitMacroOverrides(raw_ostream &Out, + ArrayRef<SubmoduleID> Overridden) { + if (!Overridden.empty()) { + 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) + LE.write<uint32_t>(Overridden[I]); + } + } + void EmitData(raw_ostream& Out, IdentifierInfo* II, IdentID ID, unsigned) { - MacroDirective *Macro = 0; + using namespace llvm::support; + endian::Writer<little> LE(Out); + MacroDirective *Macro = nullptr; if (!isInterestingIdentifier(II, Macro)) { - clang::io::Emit32(Out, ID << 1); + LE.write<uint32_t>(ID << 1); return; } - clang::io::Emit32(Out, (ID << 1) | 0x01); + LE.write<uint32_t>((ID << 1) | 0x01); uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID(); assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); - clang::io::Emit16(Out, Bits); + LE.write<uint16_t>(Bits); Bits = 0; bool HadMacroDefinition = hadMacroDefinition(II, Macro); Bits = (Bits << 1) | unsigned(HadMacroDefinition); @@ -3116,21 +3213,30 @@ public: Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); - clang::io::Emit16(Out, Bits); + LE.write<uint16_t>(Bits); if (HadMacroDefinition) { - clang::io::Emit32(Out, Writer.getMacroDirectivesOffset(II)); + LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II)); if (IsModule) { // Write the IDs of macros coming from different submodules. SubmoduleID ModID; - for (DefMacroDirective * - DefMD = getFirstPublicSubmoduleMacro(Macro, ModID); - DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) { - MacroID InfoID = Writer.getMacroID(DefMD->getInfo()); - assert(InfoID); - clang::io::Emit32(Out, InfoID); + llvm::SmallVector<SubmoduleID, 4> Overridden; + for (MacroDirective * + MD = getFirstPublicSubmoduleMacro(Macro, ModID); + MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) { + MacroID InfoID = 0; + emitMacroOverrides(Out, Overridden); + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + 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); + } } - clang::io::Emit32(Out, 0); + emitMacroOverrides(Out, Overridden); + LE.write<uint32_t>(0); } } @@ -3145,7 +3251,7 @@ public: for (SmallVectorImpl<Decl *>::reverse_iterator D = Decls.rbegin(), DEnd = Decls.rend(); D != DEnd; ++D) - clang::io::Emit32(Out, Writer.getDeclID(getMostRecentLocalDecl(*D))); + LE.write<uint32_t>(Writer.getDeclID(getMostRecentLocalDecl(*D))); } /// \brief Returns the most recent local decl or the given decl if there are @@ -3184,7 +3290,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, // Create and write out the blob that contains the identifier // strings. { - OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; + llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); // Look for any identifiers that were named while processing the @@ -3214,10 +3320,11 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, SmallString<4096> IdentifierTable; uint32_t BucketOffset; { + using namespace llvm::support; ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); + endian::Writer<little>(Out).write<uint32_t>(0); BucketOffset = Generator.Emit(Out, Trait); } @@ -3272,9 +3379,12 @@ public: typedef DeclContext::lookup_result data_type; typedef const data_type& data_type_ref; + typedef unsigned hash_value_type; + typedef unsigned offset_type; + explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { } - unsigned ComputeHash(DeclarationName Name) { + hash_value_type ComputeHash(DeclarationName Name) { llvm::FoldingSetNodeID ID; ID.AddInteger(Name.getNameKind()); @@ -3306,6 +3416,8 @@ public: std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, DeclarationName Name, data_type_ref Lookup) { + using namespace llvm::support; + endian::Writer<little> LE(Out); unsigned KeyLen = 1; switch (Name.getNameKind()) { case DeclarationName::Identifier: @@ -3324,35 +3436,35 @@ public: case DeclarationName::CXXUsingDirective: break; } - clang::io::Emit16(Out, KeyLen); + LE.write<uint16_t>(KeyLen); // 2 bytes for num of decls and 4 for each DeclID. unsigned DataLen = 2 + 4 * Lookup.size(); - clang::io::Emit16(Out, DataLen); + LE.write<uint16_t>(DataLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) { - using namespace clang::io; - - Emit8(Out, Name.getNameKind()); + using namespace llvm::support; + endian::Writer<little> LE(Out); + LE.write<uint8_t>(Name.getNameKind()); switch (Name.getNameKind()) { case DeclarationName::Identifier: - Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo())); + LE.write<uint32_t>(Writer.getIdentifierRef(Name.getAsIdentifierInfo())); return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector())); + LE.write<uint32_t>(Writer.getSelectorRef(Name.getObjCSelector())); return; case DeclarationName::CXXOperatorName: assert(Name.getCXXOverloadedOperator() < NUM_OVERLOADED_OPERATORS && "Invalid operator?"); - Emit8(Out, Name.getCXXOverloadedOperator()); + LE.write<uint8_t>(Name.getCXXOverloadedOperator()); return; case DeclarationName::CXXLiteralOperatorName: - Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier())); + LE.write<uint32_t>(Writer.getIdentifierRef(Name.getCXXLiteralIdentifier())); return; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: @@ -3366,17 +3478,134 @@ public: void EmitData(raw_ostream& Out, key_type_ref, data_type Lookup, unsigned DataLen) { + using namespace llvm::support; + endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; - clang::io::Emit16(Out, Lookup.size()); + LE.write<uint16_t>(Lookup.size()); for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end(); I != E; ++I) - clang::io::Emit32(Out, Writer.GetDeclRef(*I)); + LE.write<uint32_t>(Writer.GetDeclRef(*I)); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; } // end anonymous namespace +template<typename Visitor> +static void visitLocalLookupResults(const DeclContext *ConstDC, + bool NeedToReconcileExternalVisibleStorage, + Visitor AddLookupResult) { + // FIXME: We need to build the lookups table, which is logically const. + DeclContext *DC = const_cast<DeclContext*>(ConstDC); + assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table"); + + SmallVector<DeclarationName, 16> ExternalNames; + for (auto &Lookup : *DC->buildLookup()) { + if (Lookup.second.hasExternalDecls() || + NeedToReconcileExternalVisibleStorage) { + // We don't know for sure what declarations are found by this name, + // because the external source might have a different set from the set + // that are in the lookup map, and we can't update it now without + // risking invalidating our lookup iterator. So add it to a queue to + // deal with later. + ExternalNames.push_back(Lookup.first); + continue; + } + + AddLookupResult(Lookup.first, Lookup.second.getLookupResult()); + } + + // Add the names we needed to defer. Note, this shouldn't add any new decls + // to the list we need to serialize: any new declarations we find here should + // be imported from an external source. + // FIXME: What if the external source isn't an ASTReader? + for (const auto &Name : ExternalNames) + AddLookupResult(Name, DC->lookup(Name)); +} + +void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) { + if (UpdatedDeclContexts.insert(DC) && 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); + }); + } +} + +uint32_t +ASTWriter::GenerateNameLookupTable(const DeclContext *DC, + llvm::SmallVectorImpl<char> &LookupTable) { + assert(!DC->LookupPtr.getInt() && "must call buildLookups first"); + + llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> + Generator; + ASTDeclContextNameLookupTrait Trait(*this); + + // Create the on-disk hash table representation. + DeclarationName ConstructorName; + DeclarationName ConversionName; + SmallVector<NamedDecl *, 8> ConstructorDecls; + SmallVector<NamedDecl *, 4> ConversionDecls; + + visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage, + [&](DeclarationName Name, + DeclContext::lookup_result Result) { + if (Result.empty()) + return; + + // Different DeclarationName values of certain kinds are mapped to + // identical serialized keys, because we don't want to use type + // identifiers in the keys (since type ids are local to the module). + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + // There may be different CXXConstructorName DeclarationName values + // in a DeclContext because a UsingDecl that inherits constructors + // has the DeclarationName of the inherited constructors. + if (!ConstructorName) + ConstructorName = Name; + ConstructorDecls.append(Result.begin(), Result.end()); + return; + + case DeclarationName::CXXConversionFunctionName: + if (!ConversionName) + ConversionName = Name; + ConversionDecls.append(Result.begin(), Result.end()); + return; + + default: + break; + } + + Generator.insert(Name, Result, Trait); + }); + + // Add the constructors. + if (!ConstructorDecls.empty()) { + Generator.insert(ConstructorName, + DeclContext::lookup_result(ConstructorDecls.begin(), + ConstructorDecls.end()), + Trait); + } + + // Add the conversion functions. + if (!ConversionDecls.empty()) { + Generator.insert(ConversionName, + DeclContext::lookup_result(ConversionDecls.begin(), + ConversionDecls.end()), + Trait); + } + + // Create the on-disk hash table in a buffer. + llvm::raw_svector_ostream Out(LookupTable); + // Make sure that no bucket is at offset 0 + using namespace llvm::support; + endian::Writer<little>(Out).write<uint32_t>(0); + return Generator.Emit(Out, Trait); +} + /// \brief Write the block containing all of the declaration IDs /// visible from the given DeclContext. /// @@ -3407,50 +3636,9 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, if (!Map || Map->empty()) return 0; - OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator; - ASTDeclContextNameLookupTrait Trait(*this); - - // Create the on-disk hash table representation. - DeclarationName ConversionName; - SmallVector<NamedDecl *, 4> ConversionDecls; - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - DeclarationName Name = D->first; - DeclContext::lookup_result Result = D->second.getLookupResult(); - if (!Result.empty()) { - if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { - // Hash all conversion function names to the same name. The actual - // type information in conversion function name is not used in the - // key (since such type information is not stable across different - // modules), so the intended effect is to coalesce all of the conversion - // functions under a single key. - if (!ConversionName) - ConversionName = Name; - ConversionDecls.append(Result.begin(), Result.end()); - continue; - } - - Generator.insert(Name, Result, Trait); - } - } - - // Add the conversion functions - if (!ConversionDecls.empty()) { - Generator.insert(ConversionName, - DeclContext::lookup_result(ConversionDecls.begin(), - ConversionDecls.end()), - Trait); - } - // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; - uint32_t BucketOffset; - { - llvm::raw_svector_ostream Out(LookupTable); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out, Trait); - } + uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable); // Write the lookup table RecordData Record; @@ -3471,33 +3659,13 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, /// (in C++), for namespaces, and for classes with forward-declared unscoped /// enumeration members (in C++11). void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { - StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); + StoredDeclsMap *Map = DC->getLookupPtr(); if (!Map || Map->empty()) return; - OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator; - ASTDeclContextNameLookupTrait Trait(*this); - - // Create the hash table. - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - DeclarationName Name = D->first; - DeclContext::lookup_result Result = D->second.getLookupResult(); - // For any name that appears in this table, the results are complete, i.e. - // they overwrite results from previous PCHs. Merging is always a mess. - if (!Result.empty()) - Generator.insert(Name, Result, Trait); - } - // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; - uint32_t BucketOffset; - { - llvm::raw_svector_ostream Out(LookupTable); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out, Trait); - } + uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable); // Write the lookup table RecordData Record; @@ -3667,7 +3835,7 @@ void ASTWriter::WriteMergedDecls() { IEnd = Chain->MergedDecls.end(); I != IEnd; ++I) { DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID() - : getDeclID(I->first); + : GetDeclRef(I->first); assert(CanonID && "Merged declaration not known?"); Record.push_back(CanonID); @@ -3701,6 +3869,14 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record); } +/// \brief Write the state of 'pragma clang optimize' at the end of the module. +void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) { + RecordData Record; + SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation(); + AddSourceLocation(PragmaLoc, Record); + Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record); +} + //===----------------------------------------------------------------------===// // General Serialization Routines //===----------------------------------------------------------------------===// @@ -3774,8 +3950,8 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { } ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) - : Stream(Stream), Context(0), PP(0), Chain(0), WritingModule(0), - WritingAST(false), DoneWritingDeclsAndTypes(false), + : 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), @@ -3799,9 +3975,7 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) } ASTWriter::~ASTWriter() { - for (FileDeclIDsTy::iterator - I = FileDeclIDs.begin(), E = FileDeclIDs.end(); I != E; ++I) - delete I->second; + llvm::DeleteContainerSeconds(FileDeclIDs); } void ASTWriter::WriteAST(Sema &SemaRef, @@ -3824,18 +3998,18 @@ void ASTWriter::WriteAST(Sema &SemaRef, PP = &SemaRef.PP; this->WritingModule = WritingModule; WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); - Context = 0; - PP = 0; - this->WritingModule = 0; - + Context = nullptr; + PP = nullptr; + this->WritingModule = nullptr; + WritingAST = false; } template<typename Vector> static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, ASTWriter::RecordData &Record) { - for (typename Vector::iterator I = Vec.begin(0, true), E = Vec.end(); - I != E; ++I) { + for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); + I != E; ++I) { Writer.AddDeclRef(*I, Record); } } @@ -3846,7 +4020,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Module *WritingModule) { using namespace llvm; - bool isModule = WritingModule != 0; + bool isModule = WritingModule != nullptr; // Make sure that the AST reader knows to finalize itself. if (Chain) @@ -3906,6 +4080,15 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } } + // If we saw any DeclContext updates before we started writing the AST file, + // make sure all visible decls in those DeclContexts are written out. + if (!UpdatedDeclContexts.empty()) { + auto OldUpdatedDeclContexts = std::move(UpdatedDeclContexts); + UpdatedDeclContexts.clear(); + for (auto *DC : OldUpdatedDeclContexts) + AddUpdatedDeclContext(DC); + } + // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. @@ -4032,11 +4215,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); SmallVector<KindDeclIDPair, 64> NewGlobalDecls; - for (DeclContext::decl_iterator I = TU->noload_decls_begin(), - E = TU->noload_decls_end(); - I != E; ++I) { - if (!(*I)->isFromASTFile()) - NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I))); + for (const auto *I : TU->noload_decls()) { + if (!I->isFromASTFile()) + NewGlobalDecls.push_back(std::make_pair(I->getKind(), GetDeclRef(I))); } llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); @@ -4059,14 +4240,25 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. + // FIXME: Why do we not do this if there's already an update block? if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; - if (Record.empty()) { - Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); - Record.push_back(reinterpret_cast<uint64_t>(NS)); - } + if (Record.empty()) + Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); } + // Add update records for all mangling numbers and static local numbers. + // These aren't really update records, but this is a convenient way of + // tagging this rare extra data onto the declarations. + for (const auto &Number : Context.MangleNumbers) + if (!Number.first->isFromASTFile()) + DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER, + Number.second)); + for (const auto &Number : Context.StaticLocalNumbers) + if (!Number.first->isFromASTFile()) + DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, + Number.second)); + // Make sure visible decls, added to DeclContexts previously loaded from // an AST file, are registered for serialization. for (SmallVectorImpl<const Decl *>::iterator @@ -4090,9 +4282,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } } - // Resolve any declaration pointers within the declaration updates block. - ResolveDeclUpdatesBlocks(); - // Form the record of special types. RecordData SpecialTypes; AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); @@ -4104,30 +4293,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); AddTypeRef(Context.getucontext_tType(), SpecialTypes); - // Keep writing types and declarations until all types and - // declarations have been written. - Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); - WriteDeclsBlockAbbrevs(); - for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(), - E = DeclsToRewrite.end(); - I != E; ++I) - DeclTypesToEmit.push(const_cast<Decl*>(*I)); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - Stream.ExitBlock(); - - DoneWritingDeclsAndTypes = true; - - WriteFileDeclIDsMap(); - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - WriteComments(); - if (Chain) { // Write the mapping information describing our module dependencies and how // each of those modules were mapped into our own offset/ID space, so that @@ -4154,17 +4319,19 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(), MEnd = Chain->ModuleMgr.end(); M != MEnd; ++M) { + using namespace llvm::support; + endian::Writer<little> LE(Out); StringRef FileName = (*M)->FileName; - io::Emit16(Out, FileName.size()); + LE.write<uint16_t>(FileName.size()); Out.write(FileName.data(), FileName.size()); - io::Emit32(Out, (*M)->SLocEntryBaseOffset); - io::Emit32(Out, (*M)->BaseIdentifierID); - io::Emit32(Out, (*M)->BaseMacroID); - io::Emit32(Out, (*M)->BasePreprocessedEntityID); - io::Emit32(Out, (*M)->BaseSubmoduleID); - io::Emit32(Out, (*M)->BaseSelectorID); - io::Emit32(Out, (*M)->BaseDeclID); - io::Emit32(Out, (*M)->BaseTypeIndex); + 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); } } Record.clear(); @@ -4172,6 +4339,41 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, Buffer.data(), Buffer.size()); } + + RecordData DeclUpdatesOffsetsRecord; + + // 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(); + for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(), + E = DeclsToRewrite.end(); + I != E; ++I) + DeclTypesToEmit.push(const_cast<Decl*>(*I)); + do { + WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); + while (!DeclTypesToEmit.empty()) { + DeclOrType DOT = DeclTypesToEmit.front(); + DeclTypesToEmit.pop(); + if (DOT.isType()) + WriteType(DOT.getType()); + else + WriteDecl(Context, DOT.getDecl()); + } + } while (!DeclUpdates.empty()); + Stream.ExitBlock(); + + DoneWritingDeclsAndTypes = true; + + // These things can only be done once we've written out decls and types. + WriteTypeDeclOffsets(); + if (!DeclUpdatesOffsetsRecord.empty()) + Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + WriteCXXBaseSpecifiersOffsets(); + WriteFileDeclIDsMap(); + WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); + + WriteComments(); WritePreprocessor(PP, isModule); WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); WriteSelectors(SemaRef); @@ -4179,12 +4381,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); - - WriteTypeDeclOffsets(); WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule); - WriteCXXBaseSpecifiersOffsets(); - // If we're emitting a module, write out the submodule information. if (WritingModule) WriteSubmodules(WritingModule); @@ -4192,8 +4390,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); // Write the record containing external, unnamed definitions. - if (!ExternalDefinitions.empty()) - Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions); + if (!EagerlyDeserializedDecls.empty()) + Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); // Write the record containing tentative definitions. if (!TentativeDefinitions.empty()) @@ -4250,40 +4448,53 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); // Write the visible updates to DeclContexts. - for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator - I = UpdatedDeclContexts.begin(), - E = UpdatedDeclContexts.end(); - I != E; ++I) - WriteDeclContextVisibleUpdate(*I); + for (auto *DC : UpdatedDeclContexts) + WriteDeclContextVisibleUpdate(DC); if (!WritingModule) { // Write the submodules that were imported, if any. - RecordData ImportedModules; - for (ASTContext::import_iterator I = Context.local_import_begin(), - IEnd = Context.local_import_end(); - I != IEnd; ++I) { + struct ModuleInfo { + uint64_t ID; + Module *M; + ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {} + }; + llvm::SmallVector<ModuleInfo, 64> Imports; + for (const auto *I : Context.local_imports()) { assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end()); - ImportedModules.push_back(SubmoduleIDs[I->getImportedModule()]); + Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()], + I->getImportedModule())); } - if (!ImportedModules.empty()) { - // Sort module IDs. - llvm::array_pod_sort(ImportedModules.begin(), ImportedModules.end()); - - // Unique module IDs. - ImportedModules.erase(std::unique(ImportedModules.begin(), - ImportedModules.end()), - ImportedModules.end()); - + + if (!Imports.empty()) { + auto Cmp = [](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.end()); + + RecordData ImportedModules; + for (const auto &Import : Imports) { + ImportedModules.push_back(Import.ID); + // FIXME: If the module has macros imported then later has declarations + // imported, this location won't be the right one as a location for the + // declaration imports. + AddSourceLocation(Import.M->MacroVisibilityLoc, ImportedModules); + } + Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); } } - WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); WriteRedeclarations(); WriteMergedDecls(); WriteObjCCategories(); WriteLateParsedTemplates(SemaRef); + if(!WritingModule) + WriteOptimizePragmaOptions(SemaRef); // Some simple statistics Record.clear(); @@ -4295,64 +4506,129 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.ExitBlock(); } -/// \brief Go through the declaration update blocks and resolve declaration -/// pointers into declaration IDs. -void ASTWriter::ResolveDeclUpdatesBlocks() { - for (DeclUpdateMap::iterator - I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) { - const Decl *D = I->first; - UpdateRecord &URec = I->second; - +void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { + if (DeclUpdates.empty()) + return; + + DeclUpdateMap LocalUpdates; + LocalUpdates.swap(DeclUpdates); + + for (auto &DeclUpdate : LocalUpdates) { + const Decl *D = DeclUpdate.first; if (isRewritten(D)) - continue; // The decl will be written completely + continue; // The decl will be written completely,no need to store updates. - unsigned Idx = 0, N = URec.size(); - while (Idx < N) { - switch ((DeclUpdateKind)URec[Idx++]) { + bool HasUpdatedBody = false; + RecordData Record; + for (auto &Update : DeclUpdate.second) { + DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind(); + + Record.push_back(Kind); + switch (Kind) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: - URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx])); - ++Idx; + assert(Update.getDecl() && "no decl to add?"); + Record.push_back(GetDeclRef(Update.getDecl())); break; case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: - case UPD_DECL_MARKED_USED: - ++Idx; + AddSourceLocation(Update.getLoc(), Record); + break; + + case UPD_CXX_INSTANTIATED_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_CLASS_DEFINITION: { + auto *RD = cast<CXXRecordDecl>(D); + AddUpdatedDeclContext(RD->getPrimaryContext()); + AddCXXDefinitionData(RD, Record); + Record.push_back(WriteDeclContextLexicalBlock( + *Context, const_cast<CXXRecordDecl *>(RD))); + + // This state is sometimes updated by template instantiation, when we + // switch from the specialization referring to the template declaration + // to it referring to the template definition. + if (auto *MSInfo = RD->getMemberSpecializationInfo()) { + Record.push_back(MSInfo->getTemplateSpecializationKind()); + AddSourceLocation(MSInfo->getPointOfInstantiation(), Record); + } else { + auto *Spec = cast<ClassTemplateSpecializationDecl>(RD); + Record.push_back(Spec->getTemplateSpecializationKind()); + AddSourceLocation(Spec->getPointOfInstantiation(), Record); + + // The instantiation might have been resolved to a partial + // specialization. If so, record which one. + auto From = Spec->getInstantiatedFrom(); + if (auto PartialSpec = + From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) { + Record.push_back(true); + AddDeclRef(PartialSpec, Record); + AddTemplateArgumentList(&Spec->getTemplateInstantiationArgs(), + Record); + } else { + Record.push_back(false); + } + } + Record.push_back(RD->getTagKind()); + AddSourceLocation(RD->getLocation(), Record); + AddSourceLocation(RD->getLocStart(), Record); + AddSourceLocation(RD->getRBraceLoc(), Record); + + // 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); + + // FIXME: Ensure we don't get here for explicit instantiations. + break; + } + + case UPD_CXX_RESOLVED_EXCEPTION_SPEC: + addExceptionSpec( + *this, + cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>(), + Record); break; case UPD_CXX_DEDUCED_RETURN_TYPE: - URec[Idx] = GetOrCreateTypeID( - QualType::getFromOpaquePtr(reinterpret_cast<void *>(URec[Idx]))); - ++Idx; + Record.push_back(GetOrCreateTypeID(Update.getType())); + break; + + case UPD_DECL_MARKED_USED: + break; + + case UPD_MANGLING_NUMBER: + case UPD_STATIC_LOCAL_NUMBER: + Record.push_back(Update.getNumber()); break; } } - } -} -void ASTWriter::WriteDeclUpdatesBlocks() { - if (DeclUpdates.empty()) - return; + if (HasUpdatedBody) { + const FunctionDecl *Def = cast<FunctionDecl>(D); + Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION); + Record.push_back(Def->isInlined()); + AddSourceLocation(Def->getInnerLocStart(), Record); + AddFunctionDefinition(Def, Record); + } - RecordData OffsetsRecord; - Stream.EnterSubblock(DECL_UPDATES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); - for (DeclUpdateMap::iterator - I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) { - const Decl *D = I->first; - UpdateRecord &URec = I->second; + OffsetsRecord.push_back(GetDeclRef(D)); + OffsetsRecord.push_back(Stream.GetCurrentBitNo()); - if (isRewritten(D)) - continue; // The decl will be written completely,no need to store updates. + Stream.EmitRecord(DECL_UPDATES, Record); - uint64_t Offset = Stream.GetCurrentBitNo(); - Stream.EmitRecord(DECL_UPDATES, URec); + // Flush any statements that were written as part of this update record. + FlushStmts(); - OffsetsRecord.push_back(GetDeclRef(D)); - OffsetsRecord.push_back(Offset); + // Flush C++ base specifiers, if there are any. + FlushCXXBaseSpecifiers(); } - Stream.ExitBlock(); - Stream.EmitRecord(DECL_UPDATE_OFFSETS, OffsetsRecord); } void ASTWriter::WriteDeclReplacementsBlock() { @@ -4398,7 +4674,7 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor } IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { - if (II == 0) + if (!II) return 0; IdentID &ID = IdentifierIDs[II]; @@ -4411,7 +4687,7 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { // Don't emit builtin macros like __LINE__ to the AST file unless they // have been redefined by the header (in which case they are not // isBuiltinMacro). - if (MI == 0 || MI->isBuiltinMacro()) + if (!MI || MI->isBuiltinMacro()) return 0; MacroID &ID = MacroIDs[MI]; @@ -4424,7 +4700,7 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { } MacroID ASTWriter::getMacroID(MacroInfo *MI) { - if (MI == 0 || MI->isBuiltinMacro()) + if (!MI || MI->isBuiltinMacro()) return 0; assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); @@ -4441,7 +4717,7 @@ void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { } SelectorID ASTWriter::getSelectorRef(Selector Sel) { - if (Sel.getAsOpaquePtr() == 0) { + if (Sel.getAsOpaquePtr() == nullptr) { return 0; } @@ -4519,7 +4795,7 @@ void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record) { - if (TInfo == 0) { + if (!TInfo) { AddTypeRef(QualType(), Record); return; } @@ -4587,8 +4863,8 @@ void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { DeclID ASTWriter::GetDeclRef(const Decl *D) { assert(WritingAST && "Cannot request a declaration ID before AST writing"); - - if (D == 0) { + + if (!D) { return 0; } @@ -4615,7 +4891,7 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { } DeclID ASTWriter::getDeclID(const Decl *D) { - if (D == 0) + if (!D) return 0; // If D comes from an AST file, its declaration ID is already known and @@ -4648,7 +4924,7 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { assert(SM.isLocalSourceLocation(FileLoc)); FileID FID; unsigned Offset; - llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); + std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); if (FID.isInvalid()) return; assert(SM.getSLocEntry(FID).isFile()); @@ -4934,9 +5210,8 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, break; case TemplateArgument::Pack: Record.push_back(Arg.pack_size()); - for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end(); - I != E; ++I) - AddTemplateArgument(*I, Record); + for (const auto &P : Arg.pack_elements()) + AddTemplateArgument(P, Record); break; } } @@ -5068,8 +5343,7 @@ void ASTWriter::AddCXXCtorInitializers( } void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) { - assert(D->DefinitionData); - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; + auto &Data = D->data(); Record.push_back(Data.IsLambda); Record.push_back(Data.UserDeclaredConstructor); Record.push_back(Data.UserDeclaredSpecialMembers); @@ -5084,6 +5358,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.HasProtectedFields); Record.push_back(Data.HasPublicFields); Record.push_back(Data.HasMutableFields); + Record.push_back(Data.HasVariantMembers); Record.push_back(Data.HasOnlyCMembers); Record.push_back(Data.HasInClassInitializer); Record.push_back(Data.HasUninitializedReferenceMember); @@ -5094,6 +5369,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.DefaultedMoveAssignmentIsDeleted); Record.push_back(Data.DefaultedDestructorIsDeleted); Record.push_back(Data.HasTrivialSpecialMembers); + Record.push_back(Data.DeclaredNonTrivialSpecialMembers); Record.push_back(Data.HasIrrelevantDestructor); Record.push_back(Data.HasConstexprNonCopyMoveConstructor); Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr); @@ -5126,7 +5402,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec // Add lambda-specific data. if (Data.IsLambda) { - CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData(); + auto &Lambda = D->getLambdaData(); Record.push_back(Lambda.Dependent); Record.push_back(Lambda.IsGenericLambda); Record.push_back(Lambda.CaptureDefault); @@ -5136,7 +5412,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec AddDeclRef(Lambda.ContextDecl, Record); AddTypeSourceInfo(Lambda.MethodTyInfo, Record); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { - LambdaExpr::Capture &Capture = Lambda.Captures[I]; + const LambdaCapture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation(), Record); Record.push_back(Capture.isImplicit()); Record.push_back(Capture.getCaptureKind()); @@ -5146,7 +5422,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec case LCK_ByCopy: case LCK_ByRef: VarDecl *Var = - Capture.capturesVariable() ? Capture.getCapturedVar() : 0; + Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr; AddDeclRef(Var, Record); AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc() : SourceLocation(), @@ -5236,7 +5512,10 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { // A forward reference was mutated into a definition. Rewrite it. // FIXME: This happens during template instantiation, should we // have created a new definition decl instead ? - RewriteDecl(RD); + assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) && + "completed a tag from another module but not by instantiation?"); + DeclUpdates[RD].push_back( + DeclUpdate(UPD_CXX_INSTANTIATED_CLASS_DEFINITION)); } } } @@ -5266,9 +5545,7 @@ void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { // A decl coming from PCH was modified. assert(RD->isCompleteDefinition()); - UpdateRecord &Record = DeclUpdates[RD]; - Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER); - Record.push_back(reinterpret_cast<uint64_t>(D)); + DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D)); } void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, @@ -5279,9 +5556,8 @@ void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. - UpdateRecord &Record = DeclUpdates[TD]; - Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); - Record.push_back(reinterpret_cast<uint64_t>(D)); + DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, + D)); } void ASTWriter::AddedCXXTemplateSpecialization( @@ -5292,9 +5568,8 @@ void ASTWriter::AddedCXXTemplateSpecialization( if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. - UpdateRecord &Record = DeclUpdates[TD]; - Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); - Record.push_back(reinterpret_cast<uint64_t>(D)); + DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, + D)); } void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, @@ -5305,9 +5580,17 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. - UpdateRecord &Record = DeclUpdates[TD]; - Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); - Record.push_back(reinterpret_cast<uint64_t>(D)); + DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, + D)); +} + +void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) { + assert(!WritingAST && "Already writing the AST!"); + FD = FD->getCanonicalDecl(); + if (!FD->isFromASTFile()) + return; // Not a function declared in PCH and defined outside. + + DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC); } void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) { @@ -5316,9 +5599,7 @@ void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) { if (!FD->isFromASTFile()) return; // Not a function declared in PCH and defined outside. - UpdateRecord &Record = DeclUpdates[FD]; - Record.push_back(UPD_CXX_DEDUCED_RETURN_TYPE); - Record.push_back(reinterpret_cast<uint64_t>(ReturnType.getAsOpaquePtr())); + DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType)); } void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { @@ -5331,6 +5612,17 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { RewriteDecl(D); } +void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { + assert(!WritingAST && "Already writing the AST!"); + 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)); +} + void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) @@ -5338,10 +5630,9 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { // Since the actual instantiation is delayed, this really means that we need // to update the instantiation location. - UpdateRecord &Record = DeclUpdates[D]; - Record.push_back(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER); - AddSourceLocation( - D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record); + DeclUpdates[D].push_back( + DeclUpdate(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, + D->getMemberSpecializationInfo()->getPointOfInstantiation())); } void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, @@ -5375,6 +5666,5 @@ void ASTWriter::DeclarationMarkedUsed(const Decl *D) { if (!D->isFromASTFile()) return; - UpdateRecord &Record = DeclUpdates[D]; - Record.push_back(UPD_DECL_MARKED_USED); + DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED)); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp index 55f830a..47ce747 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp @@ -130,6 +130,14 @@ namespace clang { void VisitObjCPropertyDecl(ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + + void AddFunctionDefinition(const FunctionDecl *FD) { + assert(FD->doesThisDeclarationHaveABody()); + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) + Writer.AddCXXCtorInitializers(CD->CtorInitializers, + CD->NumCtorInitializers, Record); + Writer.AddStmt(FD->getBody()); + } }; } @@ -168,6 +176,24 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Record.push_back(D->getAccess()); Record.push_back(D->isModulePrivate()); Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation())); + + // If this declaration injected a name into a context different from its + // lexical context, and that context is an imported namespace, we need to + // update its visible declarations to include this name. + // + // This happens when we instantiate a class with a friend declaration or a + // function with a local extern declaration, for instance. + if (D->isOutOfLine()) { + auto *DC = D->getDeclContext(); + while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) { + if (!NS->isFromASTFile()) + break; + Writer.AddUpdatedDeclContext(NS->getPrimaryContext()); + if (!NS->isInlineNamespace()) + break; + DC = NS->getParent(); + } + } } void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { @@ -251,7 +277,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { Record.push_back(MemberInfo->getTemplateSpecializationKind()); Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record); } else { - Writer.AddDeclRef(0, Record); + Writer.AddDeclRef(nullptr, Record); } if (!D->hasAttrs() && @@ -372,7 +398,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Writer.AddTemplateArgumentList(FTSInfo->TemplateArguments, Record); // Template args as written. - Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0); + Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr); if (FTSInfo->TemplateArgumentsAsWritten) { Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs); for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs; @@ -414,9 +440,8 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { } Record.push_back(D->param_size()); - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); + for (auto P : D->params()) + Writer.AddDeclRef(P, Record); Code = serialization::DECL_FUNCTION; } @@ -424,8 +449,8 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { VisitNamedDecl(D); // FIXME: convert to LazyStmtPtr? // Unlike C/C++, method bodies will never be in header files. - bool HasBodyStuff = D->getBody() != 0 || - D->getSelfDecl() != 0 || D->getCmdDecl() != 0; + bool HasBodyStuff = D->getBody() != nullptr || + D->getSelfDecl() != nullptr || D->getCmdDecl() != nullptr; Record.push_back(HasBodyStuff); if (HasBodyStuff) { Writer.AddStmt(D->getBody()); @@ -451,13 +476,12 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway Record.push_back(D->getObjCDeclQualifier()); Record.push_back(D->hasRelatedResultType()); - Writer.AddTypeRef(D->getResultType(), Record); - Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record); + Writer.AddTypeRef(D->getReturnType(), Record); + Writer.AddTypeSourceInfo(D->getReturnTypeSourceInfo(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->param_size()); - for (ObjCMethodDecl::param_iterator P = D->param_begin(), - PEnd = D->param_end(); P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); + for (const auto *P : D->params()) + Writer.AddDeclRef(P, Record); Record.push_back(D->SelLocsKind); unsigned NumStoredSelLocs = D->getNumStoredSelLocs(); @@ -489,17 +513,14 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Writer.AddDeclRef(D->getSuperClass(), Record); Writer.AddSourceLocation(D->getSuperClassLoc(), Record); Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record); + Record.push_back(Data.HasDesignatedInitializers); // Write out the protocols that are directly referenced by the @interface. Record.push_back(Data.ReferencedProtocols.size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), - PEnd = D->protocol_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); + for (const auto *P : D->protocols()) + Writer.AddDeclRef(P, Record); + for (const auto &PL : D->protocol_locs()) + Writer.AddSourceLocation(PL, Record); // Write out the protocols that are transitively referenced. Record.push_back(Data.AllReferencedProtocols.size()); @@ -528,7 +549,6 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // FIXME: stable encoding for @public/@private/@protected/@package Record.push_back(D->getAccessControl()); Record.push_back(D->getSynthesize()); - Record.push_back(D->getBackingIvarReferencedInAccessor()); if (!D->hasAttrs() && !D->isImplicit() && @@ -551,13 +571,10 @@ void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Record.push_back(D->isThisDeclarationADefinition()); if (D->isThisDeclarationADefinition()) { Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); + for (const auto *I : D->protocols()) + Writer.AddDeclRef(I, Record); + for (const auto &PL : D->protocol_locs()) + Writer.AddSourceLocation(PL, Record); } Code = serialization::DECL_OBJC_PROTOCOL; @@ -575,13 +592,10 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Writer.AddDeclRef(D->getClassInterface(), Record); Record.push_back(D->protocol_size()); - for (ObjCCategoryDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCCategoryDecl::protocol_loc_iterator - PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); + for (const auto *I : D->protocols()) + Writer.AddDeclRef(I, Record); + for (const auto &PL : D->protocol_locs()) + Writer.AddSourceLocation(PL, Record); Code = serialization::DECL_OBJC_CATEGORY; } @@ -688,10 +702,8 @@ void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { VisitValueDecl(D); Record.push_back(D->getChainingSize()); - for (IndirectFieldDecl::chain_iterator - P = D->chain_begin(), - PEnd = D->chain_end(); P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); + for (const auto *P : D->chain()) + Writer.AddDeclRef(P, Record); Code = serialization::DECL_INDIRECTFIELD; } @@ -745,7 +757,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->hasExtInfo() && D->getFirstDecl() == D->getMostRecentDecl() && D->getInitStyle() == VarDecl::CInit && - D->getInit() == 0 && + D->getInit() == nullptr && !isa<ParmVarDecl>(D) && !isa<VarTemplateSpecializationDecl>(D) && !D->isConstexpr() && @@ -794,7 +806,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { D->getObjCDeclQualifier() == 0 && !D->isKNRPromoted() && !D->hasInheritedDefaultArg() && - D->getInit() == 0 && + D->getInit() == nullptr && !D->hasUninstantiatedDefaultArg()) // No default expr. AbbrevToUse = Writer.getDeclParmVarAbbrev(); @@ -803,7 +815,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS"); assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); - assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl"); + assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl"); assert(!D->isStaticDataMember() && "PARM_VAR_DECL can't be static data member"); } @@ -833,9 +845,7 @@ void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) { Record.push_back(D->isConversionFromLambda()); Record.push_back(D->capturesCXXThis()); Record.push_back(D->getNumCaptures()); - for (BlockDecl::capture_iterator - i = D->capture_begin(), e = D->capture_end(); i != e; ++i) { - const BlockDecl::Capture &capture = *i; + for (const auto &capture : D->captures()) { Writer.AddDeclRef(capture.getVariable(), Record); unsigned flags = 0; @@ -853,9 +863,11 @@ void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) { void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) { Record.push_back(CD->getNumParams()); VisitDecl(CD); + Record.push_back(CD->getContextParamPosition()); + Record.push_back(CD->isNothrow() ? 1 : 0); // Body is stored by VisitCapturedStmt. - for (unsigned i = 0; i < CD->getNumParams(); ++i) - Writer.AddDeclRef(CD->getParam(i), Record); + for (unsigned I = 0; I < CD->getNumParams(); ++I) + Writer.AddDeclRef(CD->getParam(I), Record); Code = serialization::DECL_CAPTURED; } @@ -911,9 +923,8 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { Decl *Parent = cast<Decl>( D->getParent()->getRedeclContext()->getPrimaryContext()); if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) { - ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent]; - Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); - Writer.AddDeclRef(D, Record); + Writer.DeclUpdates[Parent].push_back( + ASTWriter::DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, D)); } } } @@ -975,9 +986,6 @@ void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { VisitRecordDecl(D); - Record.push_back(D->isThisDeclarationADefinition()); - if (D->isThisDeclarationADefinition()) - Writer.AddCXXDefinitionData(D, Record); enum { CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization @@ -995,6 +1003,10 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { Record.push_back(CXXRecNotTemplate); } + Record.push_back(D->isThisDeclarationADefinition()); + if (D->isThisDeclarationADefinition()) + Writer.AddCXXDefinitionData(D, Record); + // Store (what we currently believe to be) the key function to avoid // deserializing every method so we can compute it. if (D->IsCompleteDefinition) @@ -1021,6 +1033,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); + Writer.AddDeclRef(D->getInheritedConstructor(), Record); Record.push_back(D->IsExplicitSpecified); Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers, Record); @@ -1091,7 +1104,7 @@ void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { Record.push_back(D->getNumTemplateParameters()); for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i) Writer.AddTemplateParameterList(D->getTemplateParameterList(i), Record); - Record.push_back(D->getFriendDecl() != 0); + Record.push_back(D->getFriendDecl() != nullptr); if (D->getFriendDecl()) Writer.AddDeclRef(D->getFriendDecl(), Record); else @@ -1143,8 +1156,6 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); Writer.AddDeclRef(&*I, Record); } - - Writer.AddTypeRef(D->getCommonPtr()->InjectedClassNameType, Record); } Code = serialization::DECL_CLASS_TEMPLATE; } @@ -1192,7 +1203,7 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( Writer.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten(), Record); // These are read/set from/to the first declaration. - if (D->getPreviousDecl() == 0) { + if (D->getPreviousDecl() == nullptr) { Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); Record.push_back(D->isMemberSpecialization()); } @@ -1268,7 +1279,7 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( Writer.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten(), Record); // These are read/set from/to the first declaration. - if (D->getPreviousDecl() == 0) { + if (D->getPreviousDecl() == nullptr) { Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); Record.push_back(D->isMemberSpecialization()); } @@ -1335,7 +1346,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { } else { // Rest of NonTypeTemplateParmDecl. Record.push_back(D->isParameterPack()); - Record.push_back(D->getDefaultArgument() != 0); + Record.push_back(D->getDefaultArgument() != nullptr); if (D->getDefaultArgument()) { Writer.AddStmt(D->getDefaultArgument()); Record.push_back(D->defaultArgumentWasInherited()); @@ -1429,10 +1440,8 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { Record.push_back(D->varlist_size()); VisitDecl(D); - for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), - E = D->varlist_end(); - I != E; ++I) - Writer.AddStmt(*I); + for (auto *I : D->varlists()) + Writer.AddStmt(I); Code = serialization::DECL_OMP_THREADPRIVATE; } @@ -1506,8 +1515,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // ObjC Ivar Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize - // getBackingIvarReferencedInAccessor - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -1817,8 +1824,10 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context) { // An ObjCMethodDecl is never considered as "required" because its // implementation container always is. - // File scoped assembly or obj-c implementation must be seen. - if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D)) + // File scoped assembly or obj-c implementation must be seen. ImportDecl is + // used by codegen to determine the set of imported modules to search for + // inputs for automatic linking. + if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D) || isa<ImportDecl>(D)) return true; return Context.DeclMustBeEmitted(D); @@ -1906,10 +1915,16 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Flush C++ base specifiers, if there are any. FlushCXXBaseSpecifiers(); - // Note "external" declarations so that we can add them to a record in the - // AST file later. - // - // FIXME: This should be renamed, the predicate is much more complicated. + // Note declarations that should be deserialized eagerly so that we can add + // them to a record in the AST file later. if (isRequiredDecl(D, Context)) - ExternalDefinitions.push_back(ID); + EagerlyDeserializedDecls.push_back(ID); +} + +void ASTWriter::AddFunctionDefinition(const FunctionDecl *FD, + RecordData &Record) { + ClearSwitchCaseIDs(); + + ASTDeclWriter W(*this, FD->getASTContext(), Record); + W.AddFunctionDefinition(FD); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp index 072fc98..a43b352 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp @@ -71,9 +71,8 @@ void ASTStmtWriter::VisitNullStmt(NullStmt *S) { void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) { VisitStmt(S); Record.push_back(S->size()); - for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end(); - CS != CSEnd; ++CS) - Writer.AddStmt(*CS); + for (auto *CS : S->body()) + Writer.AddStmt(CS); Writer.AddSourceLocation(S->getLBracLoc(), Record); Writer.AddSourceLocation(S->getRBracLoc(), Record); Code = serialization::STMT_COMPOUND; @@ -300,24 +299,20 @@ void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { Writer.AddDeclRef(S->getCapturedRecordDecl(), Record); // Capture inits - for (CapturedStmt::capture_init_iterator I = S->capture_init_begin(), - E = S->capture_init_end(); - I != E; ++I) - Writer.AddStmt(*I); + for (auto *I : S->capture_inits()) + Writer.AddStmt(I); // Body Writer.AddStmt(S->getCapturedStmt()); // Captures - for (CapturedStmt::capture_iterator I = S->capture_begin(), - E = S->capture_end(); - I != E; ++I) { - if (I->capturesThis()) - Writer.AddDeclRef(0, Record); + for (const auto &I : S->captures()) { + if (I.capturesThis()) + Writer.AddDeclRef(nullptr, Record); else - Writer.AddDeclRef(I->getCapturedVar(), Record); - Record.push_back(I->getCaptureKind()); - Writer.AddSourceLocation(I->getLocation(), Record); + Writer.AddDeclRef(I.getCapturedVar(), Record); + Record.push_back(I.getCaptureKind()); + Writer.AddSourceLocation(I.getLocation(), Record); } Code = serialization::STMT_CAPTURED; @@ -692,7 +687,7 @@ void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { // Replace them by 0 to indicate that the filler goes in that place. Expr *filler = E->getArrayFiller(); for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) - Writer.AddStmt(E->getInit(I) != filler ? E->getInit(I) : 0); + Writer.AddStmt(E->getInit(I) != filler ? E->getInit(I) : nullptr); } else { for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) Writer.AddStmt(E->getInit(I)); @@ -1056,7 +1051,7 @@ void ASTStmtWriter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { void ASTStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { Record.push_back(S->getNumCatchStmts()); - Record.push_back(S->getFinallyStmt() != 0); + Record.push_back(S->getFinallyStmt() != nullptr); Writer.AddStmt(S->getTryBody()); for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) Writer.AddStmt(S->getCatchStmt(I)); @@ -1155,6 +1150,7 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Record.push_back(E->isElidable()); Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->isListInitialization()); + Record.push_back(E->isStdInitListInitialization()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding Writer.AddSourceRange(E->getParenOrBraceRange(), Record); @@ -1402,7 +1398,7 @@ ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ if (!E->isImplicitAccess()) Writer.AddStmt(E->getBase()); else - Writer.AddStmt(0); + Writer.AddStmt(nullptr); Writer.AddTypeRef(E->getBaseType(), Record); Record.push_back(E->isArrow()); Writer.AddSourceLocation(E->getOperatorLoc(), Record); @@ -1472,7 +1468,7 @@ void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { VisitOverloadExpr(E); Record.push_back(E->isArrow()); Record.push_back(E->hasUnresolvedUsing()); - Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0); + Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : nullptr); Writer.AddTypeRef(E->getBaseType(), Record); Writer.AddSourceLocation(E->getOperatorLoc(), Record); Code = serialization::EXPR_CXX_UNRESOLVED_MEMBER; @@ -1486,30 +1482,12 @@ void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; } -void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getTrait()); - Record.push_back(E->getValue()); - Writer.AddSourceRange(E->getSourceRange(), Record); - Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record); - Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT; -} - -void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getTrait()); - Record.push_back(E->getValue()); - Writer.AddSourceRange(E->getSourceRange(), Record); - Writer.AddTypeSourceInfo(E->getLhsTypeSourceInfo(), Record); - Writer.AddTypeSourceInfo(E->getRhsTypeSourceInfo(), Record); - Code = serialization::EXPR_BINARY_TYPE_TRAIT; -} - void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { VisitExpr(E); Record.push_back(E->TypeTraitExprBits.NumArgs); Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding Record.push_back(E->TypeTraitExprBits.Value); + Writer.AddSourceRange(E->getSourceRange(), Record); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) Writer.AddTypeSourceInfo(E->getArg(I), Record); Code = serialization::EXPR_TYPE_TRAIT; @@ -1590,8 +1568,9 @@ void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); - Writer.AddStmt(E->Temporary); - Writer.AddDeclRef(E->ExtendingDecl, Record); + Writer.AddStmt(E->getTemporary()); + Writer.AddDeclRef(E->getExtendingDecl(), Record); + Record.push_back(E->getManglingNumber()); Code = serialization::EXPR_MATERIALIZE_TEMPORARY; } @@ -1672,6 +1651,12 @@ void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) { Code = serialization::STMT_SEH_TRY; } +void ASTStmtWriter::VisitSEHLeaveStmt(SEHLeaveStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getLeaveLoc(), Record); + Code = serialization::STMT_SEH_LEAVE; +} + //===----------------------------------------------------------------------===// // OpenMP Clauses. //===----------------------------------------------------------------------===// @@ -1697,59 +1682,254 @@ void OMPClauseWriter::writeClause(OMPClause *C) { Writer->Writer.AddSourceLocation(C->getLocEnd(), Record); } +void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) { + Writer->Writer.AddStmt(C->getCondition()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} + +void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) { + Writer->Writer.AddStmt(C->getCondition()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} + +void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + Writer->Writer.AddStmt(C->getNumThreads()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} + +void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) { + Writer->Writer.AddStmt(C->getSafelen()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} + +void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) { + Writer->Writer.AddStmt(C->getNumForLoops()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} + void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { Record.push_back(C->getDefaultKind()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record); } +void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) { + Record.push_back(C->getProcBindKind()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getProcBindKindKwLoc(), Record); +} + +void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) { + Record.push_back(C->getScheduleKind()); + Writer->Writer.AddStmt(C->getChunkSize()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getScheduleKindLoc(), Record); + Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record); +} + +void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *) {} + +void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {} + +void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {} + +void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {} + void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); - for (OMPPrivateClause::varlist_iterator I = C->varlist_begin(), - E = C->varlist_end(); - I != E; ++I) - Writer->Writer.AddStmt(*I); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); } void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); - for (OMPFirstprivateClause::varlist_iterator I = C->varlist_begin(), - E = C->varlist_end(); - I != E; ++I) - Writer->Writer.AddStmt(*I); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); +} + +void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); } void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); - for (OMPSharedClause::varlist_iterator I = C->varlist_begin(), - E = C->varlist_end(); - I != E; ++I) - Writer->Writer.AddStmt(*I); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); +} + +void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); + Writer->Writer.AddNestedNameSpecifierLoc(C->getQualifierLoc(), Record); + Writer->Writer.AddDeclarationNameInfo(C->getNameInfo(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); +} + +void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); + Writer->Writer.AddStmt(C->getStep()); +} + +void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); + Writer->Writer.AddStmt(C->getAlignment()); +} + +void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); +} + +void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); +} + +void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); } //===----------------------------------------------------------------------===// // OpenMP Directives. //===----------------------------------------------------------------------===// void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) { - VisitStmt(E); - Record.push_back(E->getNumClauses()); Writer.AddSourceLocation(E->getLocStart(), Record); Writer.AddSourceLocation(E->getLocEnd(), Record); OMPClauseWriter ClauseWriter(this, Record); for (unsigned i = 0; i < E->getNumClauses(); ++i) { ClauseWriter.writeClause(E->getClause(i)); } - Writer.AddStmt(E->getAssociatedStmt()); + if (E->hasAssociatedStmt()) + Writer.AddStmt(E->getAssociatedStmt()); } void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); VisitOMPExecutableDirective(D); Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; } +void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + Record.push_back(D->getCollapsedNumber()); + VisitOMPExecutableDirective(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); + Code = serialization::STMT_OMP_FOR_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_SECTIONS_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_SECTION_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_SINGLE_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_MASTER_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Writer.AddDeclarationNameInfo(D->getDirectiveName(), Record); + Code = serialization::STMT_OMP_CRITICAL_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + Record.push_back(D->getCollapsedNumber()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPParallelSectionsDirective( + OMPParallelSectionsDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TASK_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TASKYIELD_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPBarrierDirective(OMPBarrierDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_BARRIER_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_FLUSH_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// @@ -1812,7 +1992,7 @@ void ASTWriter::WriteSubStmt(Stmt *S, ParentStmtInserterRAII ParentStmtInserter(S, ParentStmts); #endif - // Redirect ASTWriter::AddStmt to collect sub stmts. + // Redirect ASTWriter::AddStmt to collect sub-stmts. SmallVector<Stmt *, 16> SubStmts; CollectedStmts = &SubStmts; @@ -1825,16 +2005,16 @@ void ASTWriter::WriteSubStmt(Stmt *S, SourceManager &SrcMgr = DeclIDs.begin()->first->getASTContext().getSourceManager(); S->dump(SrcMgr); - llvm_unreachable("Unhandled sub statement writing AST file"); + llvm_unreachable("Unhandled sub-statement writing AST file"); } #endif // Revert ASTWriter::AddStmt. CollectedStmts = &StmtsToEmit; - // Write the sub stmts in reverse order, last to first. When reading them back + // Write the sub-stmts in reverse order, last to first. When reading them back // we will read them in correct order by "pop"ing them from the Stmts stack. - // This simplifies reading and allows to store a variable number of sub stmts + // This simplifies reading and allows to store a variable number of sub-stmts // without knowing it in advance. while (!SubStmts.empty()) WriteSubStmt(SubStmts.pop_back_val(), SubStmtEntries, ParentStmts); @@ -1851,7 +2031,7 @@ void ASTWriter::FlushStmts() { // We expect to be the only consumer of the two temporary statement maps, // assert that they are empty. - assert(SubStmtEntries.empty() && "unexpected entries in sub stmt map"); + assert(SubStmtEntries.empty() && "unexpected entries in sub-stmt map"); assert(ParentStmts.empty() && "unexpected entries in parent stmt map"); for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { diff --git a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp index 7e8baa2..b5031fd 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp @@ -31,7 +31,7 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP, raw_ostream *OS, bool AllowASTWithErrors) : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()), Out(OS), - SemaPtr(0), Stream(Buffer), Writer(Stream), + SemaPtr(nullptr), Stream(Buffer), Writer(Stream), AllowASTWithErrors(AllowASTWithErrors), HasEmittedPCH(false) { } diff --git a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp index fb647b0..9858122 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -13,7 +13,7 @@ #include "ASTReaderInternals.h" #include "clang/Basic/FileManager.h" -#include "clang/Basic/OnDiskHashTable.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/Module.h" @@ -26,6 +26,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/LockFileManager.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include <cstdio> using namespace clang; @@ -71,20 +72,22 @@ public: typedef StringRef external_key_type; typedef StringRef internal_key_type; typedef SmallVector<unsigned, 2> data_type; + typedef unsigned hash_value_type; + typedef unsigned offset_type; static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { return a == b; } - static unsigned ComputeHash(const internal_key_type& a) { + static hash_value_type ComputeHash(const internal_key_type& a) { return llvm::HashString(a); } static std::pair<unsigned, unsigned> ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); + using namespace llvm::support; + unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d); + unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d); return std::make_pair(KeyLen, DataLen); } @@ -101,11 +104,11 @@ public: static data_type ReadData(const internal_key_type& k, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; + using namespace llvm::support; data_type Result; while (DataLen > 0) { - unsigned ID = ReadUnalignedLE32(d); + unsigned ID = endian::readNext<uint32_t, little, unaligned>(d); Result.push_back(ID); DataLen -= 4; } @@ -114,7 +117,8 @@ public: } }; -typedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable; +typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait> + IdentifierIndexTable; } @@ -202,7 +206,12 @@ GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer, assert(Idx == Record.size() && "More module info?"); // Record this module as an unresolved module. - UnresolvedModules[llvm::sys::path::stem(Modules[ID].FileName)] = ID; + // FIXME: this doesn't work correctly for module names containing path + // separators. + StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName); + // Remove the -<hash of ModuleMapPath> + ModuleName = ModuleName.rsplit('-').first; + UnresolvedModules[ModuleName] = ID; break; } @@ -210,16 +219,18 @@ GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer, // Wire up the identifier index. if (Record[0]) { IdentifierIndex = IdentifierIndexTable::Create( - (const unsigned char *)Blob.data() + Record[0], - (const unsigned char *)Blob.data(), - IdentifierIndexReaderTrait()); + (const unsigned char *)Blob.data() + Record[0], + (const unsigned char *)Blob.data() + sizeof(uint32_t), + (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait()); } break; } } } -GlobalModuleIndex::~GlobalModuleIndex() { } +GlobalModuleIndex::~GlobalModuleIndex() { + delete static_cast<IdentifierIndexTable *>(IdentifierIndex); +} std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> GlobalModuleIndex::readIndex(StringRef Path) { @@ -228,10 +239,11 @@ GlobalModuleIndex::readIndex(StringRef Path) { IndexPath += Path; llvm::sys::path::append(IndexPath, IndexFileName); - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; - if (llvm::MemoryBuffer::getFile(IndexPath.c_str(), Buffer) != - llvm::errc::success) - return std::make_pair((GlobalModuleIndex *)0, EC_NotFound); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr = + llvm::MemoryBuffer::getFile(IndexPath.c_str()); + if (!BufferOrErr) + return std::make_pair(nullptr, EC_NotFound); + std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get()); /// \brief The bitstream reader from which we'll read the AST file. llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(), @@ -245,10 +257,11 @@ GlobalModuleIndex::readIndex(StringRef Path) { Cursor.Read(8) != 'C' || Cursor.Read(8) != 'G' || Cursor.Read(8) != 'I') { - return std::make_pair((GlobalModuleIndex *)0, EC_IOError); + return std::make_pair(nullptr, EC_IOError); } - - return std::make_pair(new GlobalModuleIndex(Buffer.take(), Cursor), EC_None); + + return std::make_pair(new GlobalModuleIndex(Buffer.release(), Cursor), + EC_None); } void @@ -306,7 +319,7 @@ bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { // Look for the module in the global module index based on the module name. - StringRef Name = llvm::sys::path::stem(File->FileName); + StringRef Name = File->ModuleName; llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name); if (Known == UnresolvedModules.end()) { return true; @@ -341,6 +354,19 @@ void GlobalModuleIndex::printStats() { std::fprintf(stderr, "\n"); } +void GlobalModuleIndex::dump() { + llvm::errs() << "*** Global Module Index Dump:\n"; + llvm::errs() << "Module files:\n"; + for (auto &MI : Modules) { + llvm::errs() << "** " << MI.FileName << "\n"; + if (MI.File) + MI.File->dump(); + else + llvm::errs() << "\n"; + } + llvm::errs() << "\n"; +} + //----------------------------------------------------------------------------// // Global module index writer. //----------------------------------------------------------------------------// @@ -411,7 +437,7 @@ static void emitBlockID(unsigned ID, const char *Name, Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); // Emit the block name if present. - if (Name == 0 || Name[0] == 0) return; + if (!Name || Name[0] == 0) return; Record.clear(); while (*Name) Record.push_back(*Name++); @@ -458,8 +484,8 @@ namespace { unsigned DataLen) { // The first bit indicates whether this identifier is interesting. // That's all we care about. - using namespace clang::io; - unsigned RawID = ReadUnalignedLE32(d); + using namespace llvm::support; + unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d); bool IsInteresting = RawID & 0x01; return std::make_pair(k, IsInteresting); } @@ -468,7 +494,7 @@ namespace { bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Open the module file. - OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; std::string ErrorStr; Buffer.reset(FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)); if (!Buffer) { @@ -590,12 +616,13 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Handle the identifier table if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) { - typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait> - InterestingIdentifierTable; - llvm::OwningPtr<InterestingIdentifierTable> - Table(InterestingIdentifierTable::Create( - (const unsigned char *)Blob.data() + Record[0], - (const unsigned char *)Blob.data())); + typedef llvm::OnDiskIterableChainedHashTable< + InterestingASTIdentifierLookupTrait> InterestingIdentifierTable; + std::unique_ptr<InterestingIdentifierTable> Table( + InterestingIdentifierTable::Create( + (const unsigned char *)Blob.data() + Record[0], + (const unsigned char *)Blob.data() + sizeof(uint32_t), + (const unsigned char *)Blob.data())); for (InterestingIdentifierTable::data_iterator D = Table->data_begin(), DEnd = Table->data_end(); D != DEnd; ++D) { @@ -623,17 +650,21 @@ public: typedef StringRef key_type_ref; typedef SmallVector<unsigned, 2> data_type; typedef const SmallVector<unsigned, 2> &data_type_ref; + typedef unsigned hash_value_type; + typedef unsigned offset_type; - static unsigned ComputeHash(key_type_ref Key) { + static hash_value_type ComputeHash(key_type_ref Key) { return llvm::HashString(Key); } std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) { + using namespace llvm::support; + endian::Writer<little> LE(Out); unsigned KeyLen = Key.size(); unsigned DataLen = Data.size() * 4; - clang::io::Emit16(Out, KeyLen); - clang::io::Emit16(Out, DataLen); + LE.write<uint16_t>(KeyLen); + LE.write<uint16_t>(DataLen); return std::make_pair(KeyLen, DataLen); } @@ -643,8 +674,9 @@ public: void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, unsigned DataLen) { + using namespace llvm::support; for (unsigned I = 0, N = Data.size(); I != N; ++I) - clang::io::Emit32(Out, Data[I]); + endian::Writer<little>(Out).write<uint32_t>(Data[I]); } }; @@ -692,7 +724,7 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { // Write the identifier -> module file mapping. { - OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; + llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; IdentifierIndexWriterTrait Trait; // Populate the hash table. @@ -706,9 +738,10 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { SmallString<4096> IdentifierTable; uint32_t BucketOffset; { + using namespace llvm::support; llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); + endian::Writer<little>(Out).write<uint32_t>(0); BucketOffset = Generator.Emit(Out, Trait); } @@ -756,7 +789,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { GlobalModuleIndexBuilder Builder(FileMgr); // Load each of the module files. - llvm::error_code EC; + std::error_code EC; for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; D != DEnd && !EC; D.increment(EC)) { @@ -807,13 +840,12 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { return EC_IOError; // Remove the old index file. It isn't relevant any more. - bool OldIndexExisted; - llvm::sys::fs::remove(IndexPath.str(), OldIndexExisted); + llvm::sys::fs::remove(IndexPath.str()); // Rename the newly-written index file to the proper name. if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { // Rename failed; just remove the - llvm::sys::fs::remove(IndexTmpPath.str(), OldIndexExisted); + llvm::sys::fs::remove(IndexTmpPath.str()); return EC_IOError; } @@ -835,7 +867,7 @@ namespace { End = Idx.key_end(); } - virtual StringRef Next() { + StringRef Next() override { if (Current == End) return StringRef(); diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp index 2eb3971..6f2a3c2 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp @@ -21,27 +21,27 @@ using namespace serialization; using namespace reader; ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) - : Kind(Kind), File(0), DirectlyImported(false), + : Kind(Kind), File(nullptr), DirectlyImported(false), Generation(Generation), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0), - SLocEntryBaseOffset(0), SLocEntryOffsets(0), + SLocEntryBaseOffset(0), SLocEntryOffsets(nullptr), LocalNumIdentifiers(0), - IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0), - IdentifierLookupTable(0), - LocalNumMacros(0), MacroOffsets(0), + IdentifierOffsets(nullptr), BaseIdentifierID(0), + IdentifierTableData(nullptr), IdentifierLookupTable(nullptr), + LocalNumMacros(0), MacroOffsets(nullptr), BasePreprocessedEntityID(0), - PreprocessedEntityOffsets(0), NumPreprocessedEntities(0), + PreprocessedEntityOffsets(nullptr), NumPreprocessedEntities(0), LocalNumHeaderFileInfos(0), - HeaderFileInfoTableData(0), HeaderFileInfoTable(0), + HeaderFileInfoTableData(nullptr), HeaderFileInfoTable(nullptr), LocalNumSubmodules(0), BaseSubmoduleID(0), - LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0), - SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), - DeclOffsets(0), BaseDeclID(0), - LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), - FileSortedDecls(0), NumFileSortedDecls(0), - RedeclarationsMap(0), LocalNumRedeclarationsInMap(0), - ObjCCategoriesMap(0), LocalNumObjCCategoriesInMap(0), - LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0) + LocalNumSelectors(0), SelectorOffsets(nullptr), BaseSelectorID(0), + SelectorLookupTableData(nullptr), SelectorLookupTable(nullptr), + LocalNumDecls(0), DeclOffsets(nullptr), BaseDeclID(0), + LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr), + FileSortedDecls(nullptr), NumFileSortedDecls(0), + RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0), + ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0), + LocalNumTypes(0), TypeOffsets(nullptr), BaseTypeIndex(0) {} ModuleFile::~ModuleFile() { diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp index 9c4b3d9..2c10c11 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp @@ -11,13 +11,14 @@ // modules for the ASTReader. // //===----------------------------------------------------------------------===// +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleMap.h" #include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/ModuleManager.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" +#include <system_error> #ifndef NDEBUG #include "llvm/Support/GraphWriter.h" @@ -32,14 +33,14 @@ ModuleFile *ModuleManager::lookup(StringRef Name) { if (Entry) return lookup(Entry); - return 0; + return nullptr; } ModuleFile *ModuleManager::lookup(const FileEntry *File) { llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known = Modules.find(File); if (Known == Modules.end()) - return 0; + return nullptr; return Known->second; } @@ -57,7 +58,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, off_t ExpectedSize, time_t ExpectedModTime, ModuleFile *&Module, std::string &ErrorStr) { - Module = 0; + Module = nullptr; // Look for the file entry. This only fails if the expected size or // modification time differ. @@ -86,6 +87,16 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, NewModule = true; ModuleEntry = New; + New->InputFilesValidationTimestamp = 0; + if (New->Kind == MK_Module) { + std::string TimestampFilename = New->getTimestampFilename(); + vfs::Status Status; + // A cached stat value would be fine as well. + if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status)) + New->InputFilesValidationTimestamp = + Status.getLastModificationTime().toEpochTime(); + } + // Load the contents of the module if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { // The buffer was already provided for us. @@ -93,13 +104,24 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, New->Buffer.reset(Buffer); } else { // Open the AST file. - llvm::error_code ec; + std::error_code ec; if (FileName == "-") { - ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf = + llvm::MemoryBuffer::getSTDIN(); + ec = Buf.getError(); if (ec) ErrorStr = ec.message(); - } else - New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); + else + New->Buffer = std::move(Buf.get()); + } 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)); + } if (!New->Buffer) return Missing; @@ -124,24 +146,10 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return NewModule? NewlyLoaded : AlreadyLoaded; } -namespace { - /// \brief Predicate that checks whether a module file occurs within - /// the given set. - class IsInModuleFileSet : public std::unary_function<ModuleFile *, bool> { - llvm::SmallPtrSet<ModuleFile *, 4> &Removed; - - public: - IsInModuleFileSet(llvm::SmallPtrSet<ModuleFile *, 4> &Removed) - : Removed(Removed) { } - - bool operator()(ModuleFile *MF) const { - return Removed.count(MF); - } - }; -} - -void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last, - ModuleMap *modMap) { +void ModuleManager::removeModules( + ModuleIterator first, ModuleIterator last, + llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, + ModuleMap *modMap) { if (first == last) return; @@ -149,22 +157,29 @@ void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last, llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last); // Remove any references to the now-destroyed modules. - IsInModuleFileSet checkInSet(victimSet); for (unsigned i = 0, n = Chain.size(); i != n; ++i) { - Chain[i]->ImportedBy.remove_if(checkInSet); + Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) { + return victimSet.count(MF); + }); } // Delete the modules and erase them from the various structures. for (ModuleIterator victim = first; victim != last; ++victim) { Modules.erase((*victim)->File); - FileMgr.invalidateCache((*victim)->File); if (modMap) { - StringRef ModuleName = llvm::sys::path::stem((*victim)->FileName); + StringRef ModuleName = (*victim)->ModuleName; if (Module *mod = modMap->findModule(ModuleName)) { - mod->setASTFile(0); + mod->setASTFile(nullptr); } } + + // Files that didn't make it through ReadASTCore successfully will be + // rebuilt (or there was an error). Invalidate them so that we can load the + // new files that will be renamed over the old ones. + if (LoadedSuccessfully.count(*victim) == 0) + FileMgr.invalidateCache((*victim)->File); + delete *victim; } @@ -185,7 +200,7 @@ ModuleManager::VisitState *ModuleManager::allocateVisitState() { if (FirstVisitState) { VisitState *Result = FirstVisitState; FirstVisitState = FirstVisitState->NextState; - Result->NextState = 0; + Result->NextState = nullptr; return Result; } @@ -194,7 +209,7 @@ ModuleManager::VisitState *ModuleManager::allocateVisitState() { } void ModuleManager::returnVisitState(VisitState *State) { - assert(State->NextState == 0 && "Visited state is in list?"); + assert(State->NextState == nullptr && "Visited state is in list?"); State->NextState = FirstVisitState; FirstVisitState = State; } @@ -223,7 +238,7 @@ void ModuleManager::moduleFileAccepted(ModuleFile *MF) { } ModuleManager::ModuleManager(FileManager &FileMgr) - : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(0) { } + : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(nullptr) {} ModuleManager::~ModuleManager() { for (unsigned i = 0, e = Chain.size(); i != e; ++i) @@ -283,7 +298,7 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), assert(VisitOrder.size() == N && "Visitation order is wrong?"); delete FirstVisitState; - FirstVisitState = 0; + FirstVisitState = nullptr; } VisitState *State = allocateVisitState(); @@ -385,16 +400,19 @@ bool ModuleManager::lookupModuleFile(StringRef FileName, off_t ExpectedSize, time_t ExpectedModTime, const FileEntry *&File) { - File = FileMgr.getFile(FileName, /*openFile=*/false, /*cacheFailure=*/false); + // Open the file immediately to ensure there is no race between stat'ing and + // opening the file. + File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false); if (!File && FileName != "-") { return false; } if ((ExpectedSize && ExpectedSize != File->getSize()) || - (ExpectedModTime && ExpectedModTime != File->getModificationTime())) { + (ExpectedModTime && ExpectedModTime != File->getModificationTime())) + // Do not destroy File, as it may be referenced. If we need to rebuild it, + // it will be destroyed by removeModules. return true; - } return false; } @@ -434,7 +452,7 @@ namespace llvm { } std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { - return llvm::sys::path::stem(M->FileName); + return M->ModuleName; } }; } |