diff options
Diffstat (limited to 'lib/Serialization')
-rw-r--r-- | lib/Serialization/ASTCommon.cpp | 97 | ||||
-rw-r--r-- | lib/Serialization/ASTCommon.h | 8 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 992 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 660 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderInternals.h | 16 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 180 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 348 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 49 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 16 | ||||
-rw-r--r-- | lib/Serialization/GlobalModuleIndex.cpp | 76 | ||||
-rw-r--r-- | lib/Serialization/Module.cpp | 9 | ||||
-rw-r--r-- | lib/Serialization/MultiOnDiskHashTable.h | 22 |
12 files changed, 1887 insertions, 586 deletions
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index 9c6f03cd0bb7d..da482717f450d 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -16,7 +16,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Serialization/ASTDeserializationListener.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/DJB.h" using namespace clang; @@ -91,6 +91,78 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; + case BuiltinType::ShortAccum: + ID = PREDEF_TYPE_SHORT_ACCUM_ID; + break; + case BuiltinType::Accum: + ID = PREDEF_TYPE_ACCUM_ID; + break; + case BuiltinType::LongAccum: + ID = PREDEF_TYPE_LONG_ACCUM_ID; + break; + case BuiltinType::UShortAccum: + ID = PREDEF_TYPE_USHORT_ACCUM_ID; + break; + case BuiltinType::UAccum: + ID = PREDEF_TYPE_UACCUM_ID; + break; + case BuiltinType::ULongAccum: + ID = PREDEF_TYPE_ULONG_ACCUM_ID; + break; + case BuiltinType::ShortFract: + ID = PREDEF_TYPE_SHORT_FRACT_ID; + break; + case BuiltinType::Fract: + ID = PREDEF_TYPE_FRACT_ID; + break; + case BuiltinType::LongFract: + ID = PREDEF_TYPE_LONG_FRACT_ID; + break; + case BuiltinType::UShortFract: + ID = PREDEF_TYPE_USHORT_FRACT_ID; + break; + case BuiltinType::UFract: + ID = PREDEF_TYPE_UFRACT_ID; + break; + case BuiltinType::ULongFract: + ID = PREDEF_TYPE_ULONG_FRACT_ID; + break; + case BuiltinType::SatShortAccum: + ID = PREDEF_TYPE_SAT_SHORT_ACCUM_ID; + break; + case BuiltinType::SatAccum: + ID = PREDEF_TYPE_SAT_ACCUM_ID; + break; + case BuiltinType::SatLongAccum: + ID = PREDEF_TYPE_SAT_LONG_ACCUM_ID; + break; + case BuiltinType::SatUShortAccum: + ID = PREDEF_TYPE_SAT_USHORT_ACCUM_ID; + break; + case BuiltinType::SatUAccum: + ID = PREDEF_TYPE_SAT_UACCUM_ID; + break; + case BuiltinType::SatULongAccum: + ID = PREDEF_TYPE_SAT_ULONG_ACCUM_ID; + break; + case BuiltinType::SatShortFract: + ID = PREDEF_TYPE_SAT_SHORT_FRACT_ID; + break; + case BuiltinType::SatFract: + ID = PREDEF_TYPE_SAT_FRACT_ID; + break; + case BuiltinType::SatLongFract: + ID = PREDEF_TYPE_SAT_LONG_FRACT_ID; + break; + case BuiltinType::SatUShortFract: + ID = PREDEF_TYPE_SAT_USHORT_FRACT_ID; + break; + case BuiltinType::SatUFract: + ID = PREDEF_TYPE_SAT_UFRACT_ID; + break; + case BuiltinType::SatULongFract: + ID = PREDEF_TYPE_SAT_ULONG_FRACT_ID; + break; case BuiltinType::Float16: ID = PREDEF_TYPE_FLOAT16_ID; break; @@ -100,6 +172,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break; + case BuiltinType::Char8: + ID = PREDEF_TYPE_CHAR8_ID; + break; case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break; @@ -171,7 +246,7 @@ unsigned serialization::ComputeHash(Selector Sel) { unsigned R = 5381; for (unsigned I = 0; I != N; ++I) if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) - R = llvm::HashString(II->getName(), R); + R = llvm::djbHash(II->getName(), R); return R; } @@ -231,7 +306,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { default: llvm_unreachable("Unhandled DeclContext in AST reader"); } - + llvm_unreachable("Unhandled decl kind"); } @@ -344,9 +419,21 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { return true; } - // Otherwise, we only care about anonymous class members. + // At block scope, we number everything that we need to deduplicate, since we + // can't just use name matching to keep things lined up. + // FIXME: This is only necessary for an inline function or a template or + // similar. + if (D->getLexicalDeclContext()->isFunctionOrMethod()) { + if (auto *VD = dyn_cast<VarDecl>(D)) + return VD->isStaticLocal(); + // FIXME: What about CapturedDecls (and declarations nested within them)? + return isa<TagDecl>(D) || isa<BlockDecl>(D); + } + + // Otherwise, we only care about anonymous class members / block-scope decls. + // FIXME: We need to handle lambdas and blocks within inline / templated + // variables too. if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext())) return false; return isa<TagDecl>(D) || isa<FieldDecl>(D); } - diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index 6aca453bbb890..12e26c1fc2b93 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -72,7 +72,7 @@ TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { unsigned ComputeHash(Selector Sel); -/// \brief Retrieve the "definitive" declaration that provides all of the +/// Retrieve the "definitive" declaration that provides all of the /// visible entries for the given declaration context, if there is one. /// /// The "definitive" declaration is the only place where we need to look to @@ -84,14 +84,14 @@ unsigned ComputeHash(Selector Sel); /// multiple definitions. const DeclContext *getDefinitiveDeclContext(const DeclContext *DC); -/// \brief Determine whether the given declaration kind is redeclarable. +/// Determine whether the given declaration kind is redeclarable. bool isRedeclarableDeclKind(unsigned Kind); -/// \brief Determine whether the given declaration needs an anonymous +/// Determine whether the given declaration needs an anonymous /// declaration number. bool needsAnonymousDeclarationNumber(const NamedDecl *D); -/// \brief Visit each declaration within \c DC that needs an anonymous +/// Visit each declaration within \c DC that needs an anonymous /// declaration number and call \p Visit with the declaration and its number. template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC, Fn Visit) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4ed822e04f6c8..9a3b9e1da39a3 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -61,7 +61,6 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/TokenKinds.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Frontend/PCHContainerOperations.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" @@ -104,8 +103,9 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Compression.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/DJB.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" @@ -114,6 +114,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -255,7 +256,7 @@ void ChainedASTReaderListener::readModuleFileExtension( ASTReaderListener::~ASTReaderListener() = default; -/// \brief Compare the given set of language options against an existing set of +/// Compare the given set of language options against an existing set of /// language options. /// /// \param Diags If non-NULL, diagnostics will be emitted via this engine. @@ -359,7 +360,7 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return false; } -/// \brief Compare the given set of target options against an existing set of +/// Compare the given set of target options against an existing set of /// target options. /// /// \param Diags If non-NULL, diagnostics will be emitted via this engine. @@ -395,8 +396,8 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts, ExistingTargetOpts.FeaturesAsWritten.end()); SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(), TargetOpts.FeaturesAsWritten.end()); - std::sort(ExistingFeatures.begin(), ExistingFeatures.end()); - std::sort(ReadFeatures.begin(), ReadFeatures.end()); + llvm::sort(ExistingFeatures.begin(), ExistingFeatures.end()); + llvm::sort(ReadFeatures.begin(), ReadFeatures.end()); // We compute the set difference in both directions explicitly so that we can // diagnose the differences differently. @@ -574,7 +575,7 @@ bool PCHValidator::ReadDiagnosticOptions( Complain); } -/// \brief Collect the macro definitions provided by the given preprocessor +/// Collect the macro definitions provided by the given preprocessor /// options. static void collectMacroDefinitions(const PreprocessorOptions &PPOpts, @@ -612,7 +613,7 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts, } } -/// \brief Check the preprocessor options deserialized from the control block +/// Check the preprocessor options deserialized from the control block /// against the preprocessor options in an existing preprocessor. /// /// \param Diags If non-null, produce diagnostics for any mismatches incurred. @@ -703,6 +704,17 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, // Compute the #include and #include_macros lines we need. for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) { StringRef File = ExistingPPOpts.Includes[I]; + + if (!ExistingPPOpts.ImplicitPCHInclude.empty() && + !ExistingPPOpts.PCHThroughHeader.empty()) { + // In case the through header is an include, we must add all the includes + // to the predefines so the start point can be determined. + SuggestedPredefines += "#include \""; + SuggestedPredefines += File; + SuggestedPredefines += "\"\n"; + continue; + } + if (File == ExistingPPOpts.ImplicitPCHInclude) continue; @@ -870,7 +882,7 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, } unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) { - return llvm::HashString(a); + return llvm::djbHash(a); } std::pair<unsigned, unsigned> @@ -888,7 +900,7 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) { return StringRef((const char*) d, n-1); } -/// \brief Whether the given identifier is "interesting". +/// Whether the given identifier is "interesting". static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II, bool IsModule) { return II.hadMacroDefinition() || @@ -1211,7 +1223,7 @@ void ASTReader::Error(unsigned DiagID, // Source Manager Deserialization //===----------------------------------------------------------------------===// -/// \brief Read the line table in the source manager block. +/// Read the line table in the source manager block. /// \returns true if there was an error. bool ASTReader::ParseLineTable(ModuleFile &F, const RecordData &Record) { @@ -1257,7 +1269,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F, return false; } -/// \brief Read a source manager block +/// Read a source manager block bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) { using namespace SrcMgr; @@ -1313,7 +1325,7 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) { } } -/// \brief If a header file is not found at the path that we expect it to be +/// If a header file is not found at the path that we expect it to be /// and the PCH file was moved from its original location, try to resolve the /// file by assuming that header+PCH were moved together and the header is in /// the same place relative to the PCH. @@ -1481,6 +1493,7 @@ bool ASTReader::ReadSLocEntry(int ID) { SourceMgr.createExpansionLoc(SpellingLoc, ReadSourceLocation(*F, Record[2]), ReadSourceLocation(*F, Record[3]), + Record[5], Record[4], ID, BaseOffset + Record[0]); @@ -1510,7 +1523,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { return std::make_pair(M->ImportLoc, StringRef(M->ModuleName)); } -/// \brief Find the location where the module F is imported. +/// Find the location where the module F is imported. SourceLocation ASTReader::getImportLocation(ModuleFile *F) { if (F->ImportLoc.isValid()) return F->ImportLoc; @@ -1856,7 +1869,7 @@ void ASTReader::ReadDefinedMacros() { namespace { - /// \brief Visitor class used to look up identifirs in an AST file. + /// Visitor class used to look up identifirs in an AST file. class IdentifierLookupVisitor { StringRef Name; unsigned NameHash; @@ -1900,7 +1913,7 @@ namespace { return true; } - // \brief Retrieve the identifier info found within the module + // Retrieve the identifier info found within the module // files. IdentifierInfo *getIdentifierInfo() const { return Found; } }; @@ -2136,7 +2149,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { } // Check if there was a request to override the contents of the file - // that was part of the precompiled header. Overridding such a file + // that was part of the precompiled header. Overriding such a file // can lead to problems when lexing using the source locations from the // PCH. SourceManager &SM = getSourceManager(); @@ -2208,7 +2221,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { return IF; } -/// \brief If we are loading a relocatable PCH or module file, and the filename +/// If we are loading a relocatable PCH or module file, and the filename /// is not an absolute path, add the system or module root to the beginning of /// the file name. void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) { @@ -2480,7 +2493,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, return VersionMismatch; } - bool hasErrors = Record[6]; + bool hasErrors = Record[7]; if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) { Diag(diag::err_pch_with_compiler_errors); return HadErrors; @@ -2498,6 +2511,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.HasTimestamps = Record[5]; + F.PCHHasObjectFile = Record[6]; + const std::string &CurBranch = getClangFullRepositoryVersion(); StringRef ASTBranch = Blob; if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { @@ -2611,7 +2626,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, "MODULE_DIRECTORY found before MODULE_NAME"); // If we've already loaded a module map file covering this module, we may // have a better path for it (relative to the current build). - Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + Module *M = PP.getHeaderSearchInfo().lookupModule( + F.ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ true); if (M && M->Directory) { // If we're implicitly loading a module, the base directory can't // change between the build and use. @@ -3215,6 +3232,24 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } + case PPD_SKIPPED_RANGES: { + F.PreprocessedSkippedRangeOffsets = (const PPSkippedRange*)Blob.data(); + assert(Blob.size() % sizeof(PPSkippedRange) == 0); + F.NumPreprocessedSkippedRanges = Blob.size() / sizeof(PPSkippedRange); + + if (!PP.getPreprocessingRecord()) + PP.createPreprocessingRecord(); + if (!PP.getPreprocessingRecord()->getExternalSource()) + PP.getPreprocessingRecord()->SetExternalSource(*this); + F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord() + ->allocateSkippedRanges(F.NumPreprocessedSkippedRanges); + + if (F.NumPreprocessedSkippedRanges > 0) + GlobalSkippedRangeMap.insert( + std::make_pair(F.BasePreprocessedSkippedRangeID, &F)); + break; + } + case DECL_UPDATE_OFFSETS: if (Record.size() % 2 != 0) { Error("invalid DECL_UPDATE_OFFSETS block in AST file"); @@ -3648,7 +3683,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, return Success; } -/// \brief Move the given method to the back of the global list of methods. +/// Move the given method to the back of the global list of methods. static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { // Find the entry for this selector in the method pool. Sema::GlobalMethodPool::iterator Known @@ -3801,7 +3836,7 @@ static void updateModuleTimestamp(ModuleFile &MF) { OS.clear_error(); // Avoid triggering a fatal error. } -/// \brief Given a cursor at the start of an AST file, scan ahead and drop the +/// Given a cursor at the start of an AST file, scan ahead and drop the /// cursor into the start of the given block ID, returning false on success and /// true on failure. static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) { @@ -4068,7 +4103,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, static ASTFileSignature readASTFileSignature(StringRef PCH); -/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'. +/// Whether \p Stream starts with the AST/PCH file magic number 'CPCH'. static bool startsWithASTFileMagic(BitstreamCursor &Stream) { return Stream.canSkipToPos(4) && Stream.Read(8) == 'C' && @@ -4559,7 +4594,7 @@ void ASTReader::finalizeForWriting() { // Nothing to do for now. } -/// \brief Reads and return the signature record from \p PCH's control block, or +/// Reads and return the signature record from \p PCH's control block, or /// else returns 0. static ASTFileSignature readASTFileSignature(StringRef PCH) { BitstreamCursor Stream(PCH); @@ -4585,7 +4620,7 @@ static ASTFileSignature readASTFileSignature(StringRef PCH) { } } -/// \brief Retrieve the name of the original source file name +/// Retrieve the name of the original source file name /// directly from the AST file, without actually loading the AST /// file. std::string ASTReader::getOriginalSourceFile( @@ -4791,7 +4826,8 @@ bool ASTReader::readASTFileControlBlock( unsigned NumInputFiles = Record[0]; unsigned NumUserFiles = Record[1]; - const uint64_t *InputFileOffs = (const uint64_t *)Blob.data(); + const llvm::support::unaligned_uint64_t *InputFileOffs = + (const llvm::support::unaligned_uint64_t *)Blob.data(); for (unsigned I = 0; I != NumInputFiles; ++I) { // Go find this input file. bool isSystemFile = I >= NumUserFiles; @@ -4961,7 +4997,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; case SUBMODULE_DEFINITION: { - if (Record.size() < 8) { + if (Record.size() < 12) { Error("malformed module definition"); return Failure; } @@ -4979,6 +5015,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { bool InferExplicitSubmodules = Record[Idx++]; bool InferExportWildcard = Record[Idx++]; bool ConfigMacrosExhaustive = Record[Idx++]; + bool ModuleMapIsPrivate = Record[Idx++]; Module *ParentModule = nullptr; if (Parent) @@ -5026,6 +5063,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; CurrentModule->InferExportWildcard = InferExportWildcard; CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive; + CurrentModule->ModuleMapIsPrivate = ModuleMapIsPrivate; if (DeserializationListener) DeserializationListener->ModuleRead(GlobalID, CurrentModule); @@ -5152,6 +5190,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; case SUBMODULE_LINK_LIBRARY: + ModMap.resolveLinkAsDependencies(CurrentModule); CurrentModule->LinkLibraries.push_back( Module::LinkLibrary(Blob, Record[0])); break; @@ -5184,12 +5223,13 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { case SUBMODULE_EXPORT_AS: CurrentModule->ExportAsModule = Blob.str(); + ModMap.addLinkAsDependency(CurrentModule); break; } } } -/// \brief Parse the record that corresponds to a LangOptions data +/// Parse the record that corresponds to a LangOptions data /// structure. /// /// This routine parses the language options from the AST file and then gives @@ -5387,6 +5427,20 @@ ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) { Mod.FileSortedDecls + Mod.NumFileSortedDecls)); } +SourceRange ASTReader::ReadSkippedRange(unsigned GlobalIndex) { + auto I = GlobalSkippedRangeMap.find(GlobalIndex); + assert(I != GlobalSkippedRangeMap.end() && + "Corrupted global skipped range map"); + ModuleFile *M = I->second; + unsigned LocalIndex = GlobalIndex - M->BasePreprocessedSkippedRangeID; + assert(LocalIndex < M->NumPreprocessedSkippedRanges); + PPSkippedRange RawRange = M->PreprocessedSkippedRangeOffsets[LocalIndex]; + SourceRange Range(TranslateSourceLocation(*M, RawRange.getBegin()), + TranslateSourceLocation(*M, RawRange.getEnd())); + assert(Range.isValid()); + return Range; +} + PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { PreprocessedEntityID PPID = Index+1; std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); @@ -5474,7 +5528,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { llvm_unreachable("Invalid PreprocessorDetailRecordTypes"); } -/// \brief Find the next module that contains entities and return the ID +/// Find the next module that contains entities and return the ID /// of the first entry. /// /// \param SLocMapI points at a chunk of a module that contains no @@ -5577,7 +5631,7 @@ PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc, return M.BasePreprocessedEntityID + (PPI - pp_begin); } -/// \brief Returns a pair of [Begin, End) indices of preallocated +/// Returns a pair of [Begin, End) indices of preallocated /// preprocessed entities that \arg Range encompasses. std::pair<unsigned, unsigned> ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) { @@ -5591,7 +5645,7 @@ std::pair<unsigned, unsigned> return std::make_pair(BeginID, EndID); } -/// \brief Optionally returns true or false if the preallocated preprocessed +/// Optionally returns true or false if the preallocated preprocessed /// entity with index \arg Index came from file \arg FID. Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, FileID FID) { @@ -5615,7 +5669,7 @@ Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, namespace { - /// \brief Visitor used to search for information about a header file. + /// Visitor used to search for information about a header file. class HeaderFileInfoVisitor { const FileEntry *FE; Optional<HeaderFileInfo> HFI; @@ -5729,6 +5783,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { Initial.ExtBehavior = (diag::Severity)Flags; FirstState = ReadDiagState(Initial, SourceLocation(), true); + assert(F.OriginalSourceFileID.isValid()); + // Set up the root buffer of the module to start with the initial // diagnostic state of the module itself, to cover files that contain no // explicit transitions (for which we did not serialize anything). @@ -5749,6 +5805,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { "Invalid data, missing pragma diagnostic states"); SourceLocation Loc = ReadSourceLocation(F, Record[Idx++]); auto IDAndOffset = SourceMgr.getDecomposedLoc(Loc); + assert(IDAndOffset.first.isValid() && "invalid FileID for transition"); assert(IDAndOffset.second == 0 && "not a start location for a FileID"); unsigned Transitions = Record[Idx++]; @@ -5792,7 +5849,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { } } -/// \brief Get the correct cursor and offset for loading a type. +/// Get the correct cursor and offset for loading a type. ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index); assert(I != GlobalTypeMap.end() && "Corrupted global type map"); @@ -5800,7 +5857,7 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]); } -/// \brief Read and return the type with the given index.. +/// Read and return the type with the given index.. /// /// The index is the type ID, shifted and minus the number of predefs. This /// routine actually reads the record corresponding to the type at the given @@ -5969,13 +6026,14 @@ QualType ASTReader::readTypeRecord(unsigned Index) { } case TYPE_FUNCTION_NO_PROTO: { - if (Record.size() != 7) { + if (Record.size() != 8) { Error("incorrect encoding of no-proto function type"); return QualType(); } QualType ResultType = readType(*Loc.F, Record, Idx); FunctionType::ExtInfo Info(Record[1], Record[2], Record[3], - (CallingConv)Record[4], Record[5], Record[6]); + (CallingConv)Record[4], Record[5], Record[6], + Record[7]); return Context.getFunctionNoProtoType(ResultType, Info); } @@ -5988,9 +6046,10 @@ QualType ASTReader::readTypeRecord(unsigned Index) { /*regparm*/ Record[3], static_cast<CallingConv>(Record[4]), /*produces*/ Record[5], - /*nocallersavedregs*/ Record[6]); + /*nocallersavedregs*/ Record[6], + /*nocfcheck*/ Record[7]); - unsigned Idx = 7; + unsigned Idx = 8; EPI.Variadic = Record[Idx++]; EPI.HasTrailingReturn = Record[Idx++]; @@ -6142,7 +6201,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) { ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); QualType NamedType = readType(*Loc.F, Record, Idx); - return Context.getElaboratedType(Keyword, NNS, NamedType); + TagDecl *OwnedTagDecl = ReadDeclAs<TagDecl>(*Loc.F, Record, Idx); + return Context.getElaboratedType(Keyword, NNS, NamedType, OwnedTagDecl); } case TYPE_OBJC_INTERFACE: { @@ -6311,6 +6371,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getPipeType(ElementType, ReadOnly); } + case TYPE_DEPENDENT_SIZED_VECTOR: { + unsigned Idx = 0; + QualType ElementType = readType(*Loc.F, Record, Idx); + Expr *SizeExpr = ReadExpr(*Loc.F); + SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); + unsigned VecKind = Record[Idx]; + + return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc, + (VectorType::VectorKind)VecKind); + } + case TYPE_DEPENDENT_SIZED_EXT_VECTOR: { unsigned Idx = 0; @@ -6349,7 +6420,7 @@ void ASTReader::readExceptionSpec(ModuleFile &ModuleFile, for (unsigned I = 0, N = Record[Idx++]; I != N; ++I) Exceptions.push_back(readType(ModuleFile, Record, Idx)); ESI.Exceptions = Exceptions; - } else if (EST == EST_ComputedNoexcept) { + } else if (isComputedNoexcept(EST)) { ESI.NoexceptExpr = ReadExpr(ModuleFile); } else if (EST == EST_Uninstantiated) { ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); @@ -6491,6 +6562,11 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } +void TypeLocReader::VisitDependentVectorTypeLoc( + DependentVectorTypeLoc TL) { + TL.setNameLoc(ReadSourceLocation()); +} + void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } @@ -6686,6 +6762,13 @@ void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) { TL.setKWLoc(ReadSourceLocation()); } +void ASTReader::ReadTypeLoc(ModuleFile &F, const ASTReader::RecordData &Record, + unsigned &Idx, TypeLoc TL) { + TypeLocReader TLR(F, *this, Record, Idx); + for (; !TL.isNull(); TL = TL.getNextTypeLoc()) + TLR.Visit(TL); +} + TypeSourceInfo * ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record, unsigned &Idx) { @@ -6694,9 +6777,7 @@ ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record, return nullptr; TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); - TypeLocReader TLR(F, *this, Record, Idx); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) - TLR.Visit(TL); + ReadTypeLoc(F, Record, Idx, TInfo->getTypeLoc()); return TInfo; } @@ -6774,6 +6855,78 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break; + case PREDEF_TYPE_SHORT_ACCUM_ID: + T = Context.ShortAccumTy; + break; + case PREDEF_TYPE_ACCUM_ID: + T = Context.AccumTy; + break; + case PREDEF_TYPE_LONG_ACCUM_ID: + T = Context.LongAccumTy; + break; + case PREDEF_TYPE_USHORT_ACCUM_ID: + T = Context.UnsignedShortAccumTy; + break; + case PREDEF_TYPE_UACCUM_ID: + T = Context.UnsignedAccumTy; + break; + case PREDEF_TYPE_ULONG_ACCUM_ID: + T = Context.UnsignedLongAccumTy; + break; + case PREDEF_TYPE_SHORT_FRACT_ID: + T = Context.ShortFractTy; + break; + case PREDEF_TYPE_FRACT_ID: + T = Context.FractTy; + break; + case PREDEF_TYPE_LONG_FRACT_ID: + T = Context.LongFractTy; + break; + case PREDEF_TYPE_USHORT_FRACT_ID: + T = Context.UnsignedShortFractTy; + break; + case PREDEF_TYPE_UFRACT_ID: + T = Context.UnsignedFractTy; + break; + case PREDEF_TYPE_ULONG_FRACT_ID: + T = Context.UnsignedLongFractTy; + break; + case PREDEF_TYPE_SAT_SHORT_ACCUM_ID: + T = Context.SatShortAccumTy; + break; + case PREDEF_TYPE_SAT_ACCUM_ID: + T = Context.SatAccumTy; + break; + case PREDEF_TYPE_SAT_LONG_ACCUM_ID: + T = Context.SatLongAccumTy; + break; + case PREDEF_TYPE_SAT_USHORT_ACCUM_ID: + T = Context.SatUnsignedShortAccumTy; + break; + case PREDEF_TYPE_SAT_UACCUM_ID: + T = Context.SatUnsignedAccumTy; + break; + case PREDEF_TYPE_SAT_ULONG_ACCUM_ID: + T = Context.SatUnsignedLongAccumTy; + break; + case PREDEF_TYPE_SAT_SHORT_FRACT_ID: + T = Context.SatShortFractTy; + break; + case PREDEF_TYPE_SAT_FRACT_ID: + T = Context.SatFractTy; + break; + case PREDEF_TYPE_SAT_LONG_FRACT_ID: + T = Context.SatLongFractTy; + break; + case PREDEF_TYPE_SAT_USHORT_FRACT_ID: + T = Context.SatUnsignedShortFractTy; + break; + case PREDEF_TYPE_SAT_UFRACT_ID: + T = Context.SatUnsignedFractTy; + break; + case PREDEF_TYPE_SAT_ULONG_FRACT_ID: + T = Context.SatUnsignedLongFractTy; + break; case PREDEF_TYPE_FLOAT16_ID: T = Context.Float16Ty; break; @@ -6798,6 +6951,9 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_NULLPTR_ID: T = Context.NullPtrTy; break; + case PREDEF_TYPE_CHAR8_ID: + T = Context.Char8Ty; + break; case PREDEF_TYPE_CHAR16_ID: T = Context.Char16Ty; break; @@ -7239,7 +7395,7 @@ serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, return getGlobalDeclID(F, Record[Idx++]); } -/// \brief Resolve the offset of a statement into a statement. +/// Resolve the offset of a statement into a statement. /// /// This operation will read a new statement from the external /// source each time it is called, and is meant to be used via a @@ -7432,7 +7588,7 @@ ASTReader::getLoadedLookupTables(DeclContext *Primary) const { return I == Lookups.end() ? nullptr : &I->second; } -/// \brief Under non-PCH compilation the consumer receives the objc methods +/// Under non-PCH compilation the consumer receives the objc methods /// before receiving the implementation, and codegen depends on this. /// We simulate this by deserializing and passing to consumer the methods of the /// implementation before passing the deserialized implementation decl. @@ -7735,25 +7891,25 @@ IdentifierInfo *ASTReader::get(StringRef Name) { namespace clang { - /// \brief An identifier-lookup iterator that enumerates all of the + /// An identifier-lookup iterator that enumerates all of the /// identifiers stored within a set of AST files. class ASTIdentifierIterator : public IdentifierIterator { - /// \brief The AST reader whose identifiers are being enumerated. + /// The AST reader whose identifiers are being enumerated. const ASTReader &Reader; - /// \brief The current index into the chain of AST files stored in + /// The current index into the chain of AST files stored in /// the AST reader. unsigned Index; - /// \brief The current position within the identifier lookup table + /// The current position within the identifier lookup table /// of the current AST file. ASTIdentifierLookupTable::key_iterator Current; - /// \brief The end position within the identifier lookup table of + /// The end position within the identifier lookup table of /// the current AST file. ASTIdentifierLookupTable::key_iterator End; - /// \brief Whether to skip any modules in the ASTReader. + /// Whether to skip any modules in the ASTReader. bool SkipModules; public: @@ -7889,12 +8045,12 @@ namespace serialization { return true; } - /// \brief Retrieve the instance methods found by this visitor. + /// Retrieve the instance methods found by this visitor. ArrayRef<ObjCMethodDecl *> getInstanceMethods() const { return InstanceMethods; } - /// \brief Retrieve the instance methods found by this visitor. + /// Retrieve the instance methods found by this visitor. ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { return FactoryMethods; } @@ -7912,7 +8068,7 @@ namespace serialization { } // namespace serialization } // namespace clang -/// \brief Add the given set of methods to the method list. +/// Add the given set of methods to the method list. static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods, ObjCMethodList &List) { for (unsigned I = 0, N = Methods.size(); I != N; ++I) { @@ -8151,7 +8307,7 @@ void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) { DeserializationListener->IdentifierRead(ID, II); } -/// \brief Set the globally-visible declarations associated with the given +/// Set the globally-visible declarations associated with the given /// identifier. /// /// If the AST reader is currently in a state where the given declaration IDs @@ -8328,6 +8484,11 @@ Module *ASTReader::getModule(unsigned ID) { return getSubmodule(ID); } +bool ASTReader::DeclIsFromPCHWithObjectFile(const Decl *D) { + ModuleFile *MF = getOwningModuleFile(D); + return MF && MF->PCHHasObjectFile; +} + ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) { if (ID & 1) { // It's a module, look it up by submodule ID. @@ -8682,7 +8843,7 @@ ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx, Canonicalize)); } -/// \brief Read a UnresolvedSet structure. +/// Read a UnresolvedSet structure. void ASTReader::ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; @@ -8903,7 +9064,7 @@ ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, return SourceRange(beg, end); } -/// \brief Read an integral value +/// Read an integral value llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) { unsigned BitWidth = Record[Idx++]; unsigned NumWords = llvm::APInt::getNumWords(BitWidth); @@ -8912,20 +9073,20 @@ llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) { return Result; } -/// \brief Read a signed integral value +/// Read a signed integral value llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) { bool isUnsigned = Record[Idx++]; return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned); } -/// \brief Read a floating-point value +/// Read a floating-point value llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, const llvm::fltSemantics &Sem, unsigned &Idx) { return llvm::APFloat(Sem, ReadAPInt(Record, Idx)); } -// \brief Read a string +// Read a string std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) { unsigned Len = Record[Idx++]; std::string Result(Record.data() + Idx, Record.data() + Idx + Len); @@ -8967,13 +9128,13 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const { return Diags.Report(Loc, DiagID); } -/// \brief Retrieve the identifier table associated with the +/// Retrieve the identifier table associated with the /// preprocessor. IdentifierTable &ASTReader::getIdentifierTable() { return PP.getIdentifierTable(); } -/// \brief Record that the given ID maps to the given switch-case +/// Record that the given ID maps to the given switch-case /// statement. void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { assert((*CurrSwitchCaseStmts)[ID] == nullptr && @@ -8981,7 +9142,7 @@ void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { (*CurrSwitchCaseStmts)[ID] = SC; } -/// \brief Retrieve the switch-case statement with the given ID. +/// Retrieve the switch-case statement with the given ID. SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) { assert((*CurrSwitchCaseStmts)[ID] != nullptr && "No SwitchCase with this ID"); return (*CurrSwitchCaseStmts)[ID]; @@ -9032,8 +9193,7 @@ void ASTReader::ReadComments() { bool IsTrailingComment = Record[Idx++]; bool IsAlmostTrailingComment = Record[Idx++]; Comments.push_back(new (Context) RawComment( - SR, Kind, IsTrailingComment, IsAlmostTrailingComment, - Context.getLangOpts().CommentOpts.ParseAllComments)); + SR, Kind, IsTrailingComment, IsAlmostTrailingComment)); break; } } @@ -9041,8 +9201,8 @@ void ASTReader::ReadComments() { NextCursor: // De-serialized SourceLocations get negative FileIDs for other modules, // potentially invalidating the original order. Sort it again. - std::sort(Comments.begin(), Comments.end(), - BeforeThanCompare<RawComment>(SourceMgr)); + llvm::sort(Comments.begin(), Comments.end(), + BeforeThanCompare<RawComment>(SourceMgr)); Context.Comments.addDeserializedComments(Comments); } } @@ -9230,6 +9390,19 @@ void ASTReader::finishPendingActions() { PBEnd = PendingBodies.end(); PB != PBEnd; ++PB) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) { + // For a function defined inline within a class template, force the + // canonical definition to be the one inside the canonical definition of + // the template. This ensures that we instantiate from a correct view + // of the template. + // + // Sadly we can't do this more generally: we can't be sure that all + // copies of an arbitrary class definition will have the same members + // defined (eg, some member functions may not be instantiated, and some + // special members may or may not have been implicitly defined). + if (auto *RD = dyn_cast<CXXRecordDecl>(FD->getLexicalParent())) + if (RD->isDependentContext() && !RD->isThisDeclarationADefinition()) + continue; + // FIXME: Check for =delete/=default? // FIXME: Complain about ODR violations here? const FunctionDecl *Defn = nullptr; @@ -9242,7 +9415,15 @@ void ASTReader::finishPendingActions() { if (!FD->isLateTemplateParsed() && !NonConstDefn->isLateTemplateParsed() && FD->getODRHash() != NonConstDefn->getODRHash()) { - PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + if (!isa<CXXMethodDecl>(FD)) { + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + } else if (FD->getLexicalParent()->isFileContext() && + NonConstDefn->getLexicalParent()->isFileContext()) { + // Only diagnose out-of-line method definitions. If they are + // in class definitions, then an error will be generated when + // processing the class bodies. + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + } } } continue; @@ -9262,7 +9443,8 @@ void ASTReader::finishPendingActions() { void ASTReader::diagnoseOdrViolations() { if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() && - PendingFunctionOdrMergeFailures.empty()) + PendingFunctionOdrMergeFailures.empty() && + PendingEnumOdrMergeFailures.empty()) return; // Trigger the import of the full definition of each class that had any @@ -9298,6 +9480,16 @@ void ASTReader::diagnoseOdrViolations() { } } + // Trigger the import of enums. + auto EnumOdrMergeFailures = std::move(PendingEnumOdrMergeFailures); + PendingEnumOdrMergeFailures.clear(); + for (auto &Merge : EnumOdrMergeFailures) { + Merge.first->decls_begin(); + for (auto &Enum : Merge.second) { + Enum->decls_begin(); + } + } + // For each declaration from a merged context, check that the canonical // definition of that context also contains a declaration of the same // entity. @@ -9380,7 +9572,8 @@ void ASTReader::diagnoseOdrViolations() { } } - if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty()) + if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty() && + EnumOdrMergeFailures.empty()) return; // Ensure we don't accidentally recursively enter deserialization while @@ -9409,6 +9602,20 @@ void ASTReader::diagnoseOdrViolations() { return Hash.CalculateHash(); }; + auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) { + Hash.clear(); + Hash.AddTemplateArgument(TA); + return Hash.CalculateHash(); + }; + + auto ComputeTemplateParameterListODRHash = + [&Hash](const TemplateParameterList *TPL) { + assert(TPL); + Hash.clear(); + Hash.AddTemplateParameterList(TPL); + return Hash.CalculateHash(); + }; + // Issue any pending ODR-failure diagnostics. for (auto &Merge : OdrMergeFailures) { // If we've already pointed out a specific problem with this class, don't @@ -9761,6 +9968,7 @@ void ASTReader::diagnoseOdrViolations() { TypeDef, Var, Friend, + FunctionTemplate, Other } FirstDiffType = Other, SecondDiffType = Other; @@ -9798,6 +10006,8 @@ void ASTReader::diagnoseOdrViolations() { return Var; case Decl::Friend: return Friend; + case Decl::FunctionTemplate: + return FunctionTemplate; } }; @@ -9884,7 +10094,7 @@ void ASTReader::diagnoseOdrViolations() { // Used with err_module_odr_violation_mismatch_decl_diff and // note_module_odr_violation_mismatch_decl_diff - enum ODRDeclDifference{ + enum ODRDeclDifference { StaticAssertCondition, StaticAssertMessage, StaticAssertOnlyMessage, @@ -9897,6 +10107,7 @@ void ASTReader::diagnoseOdrViolations() { FieldDifferentInitializers, MethodName, MethodDeleted, + MethodDefaulted, MethodVirtual, MethodStatic, MethodVolatile, @@ -9907,6 +10118,11 @@ void ASTReader::diagnoseOdrViolations() { MethodParameterName, MethodParameterSingleDefaultArgument, MethodParameterDifferentDefaultArgument, + MethodNoTemplateArguments, + MethodDifferentNumberTemplateArguments, + MethodDifferentTemplateArgument, + MethodSingleBody, + MethodDifferentBody, TypedefName, TypedefType, VarName, @@ -9917,6 +10133,13 @@ void ASTReader::diagnoseOdrViolations() { FriendTypeFunction, FriendType, FriendFunction, + FunctionTemplateDifferentNumberParameters, + FunctionTemplateParameterDifferentKind, + FunctionTemplateParameterName, + FunctionTemplateParameterSingleDefaultArgument, + FunctionTemplateParameterDifferentDefaultArgument, + FunctionTemplateParameterDifferentType, + FunctionTemplatePackParameter, }; // These lambdas have the common portions of the ODR diagnostics. This @@ -10133,8 +10356,8 @@ void ASTReader::diagnoseOdrViolations() { break; } - const bool FirstDeleted = FirstMethod->isDeleted(); - const bool SecondDeleted = SecondMethod->isDeleted(); + const bool FirstDeleted = FirstMethod->isDeletedAsWritten(); + const bool SecondDeleted = SecondMethod->isDeletedAsWritten(); if (FirstDeleted != SecondDeleted) { ODRDiagError(FirstMethod->getLocation(), FirstMethod->getSourceRange(), MethodDeleted) @@ -10147,6 +10370,20 @@ void ASTReader::diagnoseOdrViolations() { break; } + const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted(); + const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted(); + if (FirstDefaulted != SecondDefaulted) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodDefaulted) + << FirstMethodType << FirstName << FirstDefaulted; + + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodDefaulted) + << SecondMethodType << SecondName << SecondDefaulted; + Diagnosed = true; + break; + } + const bool FirstVirtual = FirstMethod->isVirtualAsWritten(); const bool SecondVirtual = SecondMethod->isVirtualAsWritten(); const bool FirstPure = FirstMethod->isPure(); @@ -10329,6 +10566,127 @@ void ASTReader::diagnoseOdrViolations() { break; } + const auto *FirstTemplateArgs = + FirstMethod->getTemplateSpecializationArgs(); + const auto *SecondTemplateArgs = + SecondMethod->getTemplateSpecializationArgs(); + + if ((FirstTemplateArgs && !SecondTemplateArgs) || + (!FirstTemplateArgs && SecondTemplateArgs)) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodNoTemplateArguments) + << FirstMethodType << FirstName << (FirstTemplateArgs != nullptr); + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodNoTemplateArguments) + << SecondMethodType << SecondName + << (SecondTemplateArgs != nullptr); + + Diagnosed = true; + break; + } + + if (FirstTemplateArgs && SecondTemplateArgs) { + // Remove pack expansions from argument list. + auto ExpandTemplateArgumentList = + [](const TemplateArgumentList *TAL) { + llvm::SmallVector<const TemplateArgument *, 8> ExpandedList; + for (const TemplateArgument &TA : TAL->asArray()) { + if (TA.getKind() != TemplateArgument::Pack) { + ExpandedList.push_back(&TA); + continue; + } + for (const TemplateArgument &PackTA : TA.getPackAsArray()) { + ExpandedList.push_back(&PackTA); + } + } + return ExpandedList; + }; + llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList = + ExpandTemplateArgumentList(FirstTemplateArgs); + llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList = + ExpandTemplateArgumentList(SecondTemplateArgs); + + if (FirstExpandedList.size() != SecondExpandedList.size()) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), + MethodDifferentNumberTemplateArguments) + << FirstMethodType << FirstName + << (unsigned)FirstExpandedList.size(); + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), + MethodDifferentNumberTemplateArguments) + << SecondMethodType << SecondName + << (unsigned)SecondExpandedList.size(); + + Diagnosed = true; + break; + } + + bool TemplateArgumentMismatch = false; + for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) { + const TemplateArgument &FirstTA = *FirstExpandedList[i], + &SecondTA = *SecondExpandedList[i]; + if (ComputeTemplateArgumentODRHash(FirstTA) == + ComputeTemplateArgumentODRHash(SecondTA)) { + continue; + } + + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), + MethodDifferentTemplateArgument) + << FirstMethodType << FirstName << FirstTA << i + 1; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), + MethodDifferentTemplateArgument) + << SecondMethodType << SecondName << SecondTA << i + 1; + + TemplateArgumentMismatch = true; + break; + } + + if (TemplateArgumentMismatch) { + Diagnosed = true; + break; + } + } + + // Compute the hash of the method as if it has no body. + auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) { + Hash.clear(); + Hash.AddFunctionDecl(D, true /*SkipBody*/); + return Hash.CalculateHash(); + }; + + // Compare the hash generated to the hash stored. A difference means + // that a body was present in the original source. Due to merging, + // the stardard way of detecting a body will not work. + const bool HasFirstBody = + ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); + const bool HasSecondBody = + ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash(); + + if (HasFirstBody != HasSecondBody) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodSingleBody) + << FirstMethodType << FirstName << HasFirstBody; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodSingleBody) + << SecondMethodType << SecondName << HasSecondBody; + Diagnosed = true; + break; + } + + if (HasFirstBody && HasSecondBody) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodDifferentBody) + << FirstMethodType << FirstName; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodDifferentBody) + << SecondMethodType << SecondName; + Diagnosed = true; + break; + } + break; } case TypeAlias: @@ -10481,6 +10839,305 @@ void ASTReader::diagnoseOdrViolations() { Diagnosed = true; break; } + case FunctionTemplate: { + FunctionTemplateDecl *FirstTemplate = + cast<FunctionTemplateDecl>(FirstDecl); + FunctionTemplateDecl *SecondTemplate = + cast<FunctionTemplateDecl>(SecondDecl); + + TemplateParameterList *FirstTPL = + FirstTemplate->getTemplateParameters(); + TemplateParameterList *SecondTPL = + SecondTemplate->getTemplateParameters(); + + if (FirstTPL->size() != SecondTPL->size()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateDifferentNumberParameters) + << FirstTemplate << FirstTPL->size(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateDifferentNumberParameters) + << SecondTemplate << SecondTPL->size(); + + Diagnosed = true; + break; + } + + bool ParameterMismatch = false; + for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) { + NamedDecl *FirstParam = FirstTPL->getParam(i); + NamedDecl *SecondParam = SecondTPL->getParam(i); + + if (FirstParam->getKind() != SecondParam->getKind()) { + enum { + TemplateTypeParameter, + NonTypeTemplateParameter, + TemplateTemplateParameter, + }; + auto GetParamType = [](NamedDecl *D) { + switch (D->getKind()) { + default: + llvm_unreachable("Unexpected template parameter type"); + case Decl::TemplateTypeParm: + return TemplateTypeParameter; + case Decl::NonTypeTemplateParm: + return NonTypeTemplateParameter; + case Decl::TemplateTemplateParm: + return TemplateTemplateParameter; + } + }; + + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentKind) + << FirstTemplate << (i + 1) << GetParamType(FirstParam); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentKind) + << SecondTemplate << (i + 1) << GetParamType(SecondParam); + + ParameterMismatch = true; + break; + } + + if (FirstParam->getName() != SecondParam->getName()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterName) + << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier() + << FirstParam; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterName) + << SecondTemplate << (i + 1) + << (bool)SecondParam->getIdentifier() << SecondParam; + ParameterMismatch = true; + break; + } + + if (isa<TemplateTypeParmDecl>(FirstParam) && + isa<TemplateTypeParmDecl>(SecondParam)) { + TemplateTypeParmDecl *FirstTTPD = + cast<TemplateTypeParmDecl>(FirstParam); + TemplateTypeParmDecl *SecondTTPD = + cast<TemplateTypeParmDecl>(SecondParam); + bool HasFirstDefaultArgument = + FirstTTPD->hasDefaultArgument() && + !FirstTTPD->defaultArgumentWasInherited(); + bool HasSecondDefaultArgument = + SecondTTPD->hasDefaultArgument() && + !SecondTTPD->defaultArgumentWasInherited(); + if (HasFirstDefaultArgument != HasSecondDefaultArgument) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << FirstTemplate << (i + 1) << HasFirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << SecondTemplate << (i + 1) << HasSecondDefaultArgument; + ParameterMismatch = true; + break; + } + + if (HasFirstDefaultArgument && HasSecondDefaultArgument) { + QualType FirstType = FirstTTPD->getDefaultArgument(); + QualType SecondType = SecondTTPD->getDefaultArgument(); + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << FirstTemplate << (i + 1) << FirstType; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << SecondTemplate << (i + 1) << SecondType; + ParameterMismatch = true; + break; + } + } + + if (FirstTTPD->isParameterPack() != + SecondTTPD->isParameterPack()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack(); + ParameterMismatch = true; + break; + } + } + + if (isa<TemplateTemplateParmDecl>(FirstParam) && + isa<TemplateTemplateParmDecl>(SecondParam)) { + TemplateTemplateParmDecl *FirstTTPD = + cast<TemplateTemplateParmDecl>(FirstParam); + TemplateTemplateParmDecl *SecondTTPD = + cast<TemplateTemplateParmDecl>(SecondParam); + + TemplateParameterList *FirstTPL = + FirstTTPD->getTemplateParameters(); + TemplateParameterList *SecondTPL = + SecondTTPD->getTemplateParameters(); + + if (ComputeTemplateParameterListODRHash(FirstTPL) != + ComputeTemplateParameterListODRHash(SecondTPL)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << FirstTemplate << (i + 1); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << SecondTemplate << (i + 1); + ParameterMismatch = true; + break; + } + + bool HasFirstDefaultArgument = + FirstTTPD->hasDefaultArgument() && + !FirstTTPD->defaultArgumentWasInherited(); + bool HasSecondDefaultArgument = + SecondTTPD->hasDefaultArgument() && + !SecondTTPD->defaultArgumentWasInherited(); + if (HasFirstDefaultArgument != HasSecondDefaultArgument) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << FirstTemplate << (i + 1) << HasFirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << SecondTemplate << (i + 1) << HasSecondDefaultArgument; + ParameterMismatch = true; + break; + } + + if (HasFirstDefaultArgument && HasSecondDefaultArgument) { + TemplateArgument FirstTA = + FirstTTPD->getDefaultArgument().getArgument(); + TemplateArgument SecondTA = + SecondTTPD->getDefaultArgument().getArgument(); + if (ComputeTemplateArgumentODRHash(FirstTA) != + ComputeTemplateArgumentODRHash(SecondTA)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << FirstTemplate << (i + 1) << FirstTA; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << SecondTemplate << (i + 1) << SecondTA; + ParameterMismatch = true; + break; + } + } + + if (FirstTTPD->isParameterPack() != + SecondTTPD->isParameterPack()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack(); + ParameterMismatch = true; + break; + } + } + + if (isa<NonTypeTemplateParmDecl>(FirstParam) && + isa<NonTypeTemplateParmDecl>(SecondParam)) { + NonTypeTemplateParmDecl *FirstNTTPD = + cast<NonTypeTemplateParmDecl>(FirstParam); + NonTypeTemplateParmDecl *SecondNTTPD = + cast<NonTypeTemplateParmDecl>(SecondParam); + + QualType FirstType = FirstNTTPD->getType(); + QualType SecondType = SecondNTTPD->getType(); + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << FirstTemplate << (i + 1); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << SecondTemplate << (i + 1); + ParameterMismatch = true; + break; + } + + bool HasFirstDefaultArgument = + FirstNTTPD->hasDefaultArgument() && + !FirstNTTPD->defaultArgumentWasInherited(); + bool HasSecondDefaultArgument = + SecondNTTPD->hasDefaultArgument() && + !SecondNTTPD->defaultArgumentWasInherited(); + if (HasFirstDefaultArgument != HasSecondDefaultArgument) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << FirstTemplate << (i + 1) << HasFirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << SecondTemplate << (i + 1) << HasSecondDefaultArgument; + ParameterMismatch = true; + break; + } + + if (HasFirstDefaultArgument && HasSecondDefaultArgument) { + Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); + Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); + if (ComputeODRHash(FirstDefaultArgument) != + ComputeODRHash(SecondDefaultArgument)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << FirstTemplate << (i + 1) << FirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << SecondTemplate << (i + 1) << SecondDefaultArgument; + ParameterMismatch = true; + break; + } + } + + if (FirstNTTPD->isParameterPack() != + SecondNTTPD->isParameterPack()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << SecondTemplate << (i + 1) + << SecondNTTPD->isParameterPack(); + ParameterMismatch = true; + break; + } + } + } + + if (ParameterMismatch) { + Diagnosed = true; + break; + } + + break; + } } if (Diagnosed) @@ -10660,6 +11317,195 @@ void ASTReader::diagnoseOdrViolations() { Diagnosed = true; break; } + (void)Diagnosed; + assert(Diagnosed && "Unable to emit ODR diagnostic."); + } + + // Issue ODR failures diagnostics for enums. + for (auto &Merge : EnumOdrMergeFailures) { + enum ODREnumDifference { + SingleScopedEnum, + EnumTagKeywordMismatch, + SingleSpecifiedType, + DifferentSpecifiedTypes, + DifferentNumberEnumConstants, + EnumConstantName, + EnumConstantSingleInitilizer, + EnumConstantDifferentInitilizer, + }; + + // If we've already pointed out a specific problem with this enum, don't + // bother issuing a general "something's different" diagnostic. + if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) + continue; + + EnumDecl *FirstEnum = Merge.first; + std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum); + + using DeclHashes = + llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>; + auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum]( + DeclHashes &Hashes, EnumDecl *Enum) { + for (auto *D : Enum->decls()) { + // Due to decl merging, the first EnumDecl is the parent of + // Decls in both records. + if (!ODRHash::isWhitelistedDecl(D, FirstEnum)) + continue; + assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind"); + Hashes.emplace_back(cast<EnumConstantDecl>(D), + ComputeSubDeclODRHash(D)); + } + }; + DeclHashes FirstHashes; + PopulateHashes(FirstHashes, FirstEnum); + bool Diagnosed = false; + for (auto &SecondEnum : Merge.second) { + + if (FirstEnum == SecondEnum) + continue; + + std::string SecondModule = + getOwningModuleNameForDiagnostic(SecondEnum); + + auto ODRDiagError = [FirstEnum, &FirstModule, + this](SourceLocation Loc, SourceRange Range, + ODREnumDifference DiffType) { + return Diag(Loc, diag::err_module_odr_violation_enum) + << FirstEnum << FirstModule.empty() << FirstModule << Range + << DiffType; + }; + auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc, + SourceRange Range, + ODREnumDifference DiffType) { + return Diag(Loc, diag::note_module_odr_violation_enum) + << SecondModule << Range << DiffType; + }; + + if (FirstEnum->isScoped() != SecondEnum->isScoped()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + SingleScopedEnum) + << FirstEnum->isScoped(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + SingleScopedEnum) + << SecondEnum->isScoped(); + Diagnosed = true; + continue; + } + + if (FirstEnum->isScoped() && SecondEnum->isScoped()) { + if (FirstEnum->isScopedUsingClassTag() != + SecondEnum->isScopedUsingClassTag()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + EnumTagKeywordMismatch) + << FirstEnum->isScopedUsingClassTag(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + EnumTagKeywordMismatch) + << SecondEnum->isScopedUsingClassTag(); + Diagnosed = true; + continue; + } + } + + QualType FirstUnderlyingType = + FirstEnum->getIntegerTypeSourceInfo() + ? FirstEnum->getIntegerTypeSourceInfo()->getType() + : QualType(); + QualType SecondUnderlyingType = + SecondEnum->getIntegerTypeSourceInfo() + ? SecondEnum->getIntegerTypeSourceInfo()->getType() + : QualType(); + if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + SingleSpecifiedType) + << !FirstUnderlyingType.isNull(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + SingleSpecifiedType) + << !SecondUnderlyingType.isNull(); + Diagnosed = true; + continue; + } + + if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) { + if (ComputeQualTypeODRHash(FirstUnderlyingType) != + ComputeQualTypeODRHash(SecondUnderlyingType)) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + DifferentSpecifiedTypes) + << FirstUnderlyingType; + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + DifferentSpecifiedTypes) + << SecondUnderlyingType; + Diagnosed = true; + continue; + } + } + + DeclHashes SecondHashes; + PopulateHashes(SecondHashes, SecondEnum); + + if (FirstHashes.size() != SecondHashes.size()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + DifferentNumberEnumConstants) + << (int)FirstHashes.size(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + DifferentNumberEnumConstants) + << (int)SecondHashes.size(); + Diagnosed = true; + continue; + } + + for (unsigned I = 0; I < FirstHashes.size(); ++I) { + if (FirstHashes[I].second == SecondHashes[I].second) + continue; + const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first; + const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first; + + if (FirstEnumConstant->getDeclName() != + SecondEnumConstant->getDeclName()) { + + ODRDiagError(FirstEnumConstant->getLocation(), + FirstEnumConstant->getSourceRange(), EnumConstantName) + << I + 1 << FirstEnumConstant; + ODRDiagNote(SecondEnumConstant->getLocation(), + SecondEnumConstant->getSourceRange(), EnumConstantName) + << I + 1 << SecondEnumConstant; + Diagnosed = true; + break; + } + + const Expr *FirstInit = FirstEnumConstant->getInitExpr(); + const Expr *SecondInit = SecondEnumConstant->getInitExpr(); + if (!FirstInit && !SecondInit) + continue; + + if (!FirstInit || !SecondInit) { + ODRDiagError(FirstEnumConstant->getLocation(), + FirstEnumConstant->getSourceRange(), + EnumConstantSingleInitilizer) + << I + 1 << FirstEnumConstant << (FirstInit != nullptr); + ODRDiagNote(SecondEnumConstant->getLocation(), + SecondEnumConstant->getSourceRange(), + EnumConstantSingleInitilizer) + << I + 1 << SecondEnumConstant << (SecondInit != nullptr); + Diagnosed = true; + break; + } + + if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { + ODRDiagError(FirstEnumConstant->getLocation(), + FirstEnumConstant->getSourceRange(), + EnumConstantDifferentInitilizer) + << I + 1 << FirstEnumConstant; + ODRDiagNote(SecondEnumConstant->getLocation(), + SecondEnumConstant->getSourceRange(), + EnumConstantDifferentInitilizer) + << I + 1 << SecondEnumConstant; + Diagnosed = true; + break; + } + } + } + + (void)Diagnosed; assert(Diagnosed && "Unable to emit ODR diagnostic."); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index efbaf92a849ae..7e2c4829b14ce 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1,4 +1,4 @@ -//===--- ASTReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===// +//===- ASTReaderDecl.cpp - Decl Deserialization ---------------------------===// // // The LLVM Compiler Infrastructure // @@ -15,42 +15,89 @@ #include "ASTCommon.h" #include "ASTReaderInternals.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/AST/AttrIterator.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Redeclarable.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/AttrKinds.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Linkage.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/PragmaKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/SemaDiagnostic.h" +#include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" +#include "clang/Serialization/ContinuousRangeMap.h" +#include "clang/Serialization/Module.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> +#include <string> +#include <utility> using namespace clang; -using namespace clang::serialization; +using namespace serialization; //===----------------------------------------------------------------------===// // Declaration deserialization //===----------------------------------------------------------------------===// namespace clang { + class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { ASTReader &Reader; ASTRecordReader &Record; ASTReader::RecordLocation Loc; const DeclID ThisDeclID; const SourceLocation ThisDeclLoc; - typedef ASTReader::RecordData RecordData; - TypeID TypeIDForTypeDecl; + + using RecordData = ASTReader::RecordData; + + TypeID DeferredTypeID = 0; unsigned AnonymousDeclNumber; - GlobalDeclID NamedDeclForTagDecl; - IdentifierInfo *TypedefNameForLinkage; + GlobalDeclID NamedDeclForTagDecl = 0; + IdentifierInfo *TypedefNameForLinkage = nullptr; - bool HasPendingBody; + bool HasPendingBody = false; - ///\brief A flag to carry the information for a decl from the entity is + ///A flag to carry the information for a decl from the entity is /// used. We use it to delay the marking of the canonical decl as used until /// the entire declaration is deserialized and merged. - bool IsDeclMarkedUsed; + bool IsDeclMarkedUsed = false; uint64_t GetCurrentCursorOffset(); @@ -130,6 +177,8 @@ namespace clang { void MergeDefinitionData(ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD); + static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC); + static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index); @@ -144,39 +193,34 @@ namespace clang { public: RedeclarableResult(Decl *MergeWith, GlobalDeclID FirstID, bool IsKeyDecl) - : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {} + : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {} - /// \brief Retrieve the first ID. + /// Retrieve the first ID. GlobalDeclID getFirstID() const { return FirstID; } - /// \brief Is this declaration a key declaration? + /// Is this declaration a key declaration? bool isKeyDecl() const { return IsKeyDecl; } - /// \brief Get a known declaration that this should be merged with, if + /// Get a known declaration that this should be merged with, if /// any. Decl *getKnownMergeTarget() const { return MergeWith; } }; - /// \brief Class used to capture the result of searching for an existing + /// Class used to capture the result of searching for an existing /// declaration of a specific kind and name, along with the ability /// to update the place where this result was found (the declaration /// chain hanging off an identifier or the DeclContext we searched in) /// if requested. class FindExistingResult { ASTReader &Reader; - NamedDecl *New; - NamedDecl *Existing; - bool AddResult; - - unsigned AnonymousDeclNumber; - IdentifierInfo *TypedefNameForLinkage; - - void operator=(FindExistingResult &&) = delete; + NamedDecl *New = nullptr; + NamedDecl *Existing = nullptr; + bool AddResult = false; + unsigned AnonymousDeclNumber = 0; + IdentifierInfo *TypedefNameForLinkage = nullptr; public: - FindExistingResult(ASTReader &Reader) - : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false), - AnonymousDeclNumber(0), TypedefNameForLinkage(nullptr) {} + FindExistingResult(ASTReader &Reader) : Reader(Reader) {} FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing, unsigned AnonymousDeclNumber, @@ -193,9 +237,10 @@ namespace clang { Other.AddResult = false; } + FindExistingResult &operator=(FindExistingResult &&) = delete; ~FindExistingResult(); - /// \brief Suppress the addition of this result into the known set of + /// Suppress the addition of this result into the known set of /// names. void suppress() { AddResult = false; } @@ -213,11 +258,8 @@ namespace clang { ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record, ASTReader::RecordLocation Loc, DeclID thisDeclID, SourceLocation ThisDeclLoc) - : Reader(Reader), Record(Record), Loc(Loc), - ThisDeclID(thisDeclID), ThisDeclLoc(ThisDeclLoc), - TypeIDForTypeDecl(0), NamedDeclForTagDecl(0), - TypedefNameForLinkage(nullptr), HasPendingBody(false), - IsDeclMarkedUsed(false) {} + : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID), + ThisDeclLoc(ThisDeclLoc) {} template <typename T> static void AddLazySpecializations(T *D, @@ -232,7 +274,7 @@ namespace clang { if (auto &Old = LazySpecializations) { IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); - std::sort(IDs.begin(), IDs.end()); + llvm::sort(IDs.begin(), IDs.end()); IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); } @@ -265,13 +307,13 @@ namespace clang { static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D); static void markIncompleteDeclChainImpl(...); - /// \brief Determine whether this declaration has a pending body. + /// Determine whether this declaration has a pending body. bool hasPendingBody() const { return HasPendingBody; } void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&); + void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -300,19 +342,23 @@ namespace clang { void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } RedeclarableResult VisitClassTemplateSpecializationDeclImpl( ClassTemplateSpecializationDecl *D); + void VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { VisitClassTemplateSpecializationDeclImpl(D); } + void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D); RedeclarableResult VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D); + void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) { VisitVarTemplateSpecializationDeclImpl(D); } + void VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); @@ -402,18 +448,22 @@ namespace clang { void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); }; -} // end namespace clang + +} // namespace clang namespace { + /// Iterator over the redeclarations of a declaration that have already /// been merged into the same redeclaration chain. template<typename DeclT> class MergedRedeclIterator { - DeclT *Start, *Canonical, *Current; + DeclT *Start; + DeclT *Canonical = nullptr; + DeclT *Current = nullptr; + public: - MergedRedeclIterator() : Current(nullptr) {} - MergedRedeclIterator(DeclT *Start) - : Start(Start), Canonical(nullptr), Current(Start) {} + MergedRedeclIterator() = default; + MergedRedeclIterator(DeclT *Start) : Start(Start), Current(Start) {} DeclT *operator*() { return Current; } @@ -438,7 +488,8 @@ public: return A.Current != B.Current; } }; -} // end anonymous namespace + +} // namespace template <typename DeclT> static llvm::iterator_range<MergedRedeclIterator<DeclT>> @@ -472,30 +523,27 @@ void ASTDeclReader::Visit(Decl *D) { D->getCanonicalDecl()->Used |= IsDeclMarkedUsed; IsDeclMarkedUsed = false; - if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { - if (DD->DeclInfo) { - DeclaratorDecl::ExtInfo *Info = - DD->DeclInfo.get<DeclaratorDecl::ExtInfo *>(); - Info->TInfo = GetTypeSourceInfo(); - } - else { - DD->DeclInfo = GetTypeSourceInfo(); - } + if (auto *DD = dyn_cast<DeclaratorDecl>(D)) { + if (auto *TInfo = DD->getTypeSourceInfo()) + Record.readTypeLoc(TInfo->getTypeLoc()); } - if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { + if (auto *TD = dyn_cast<TypeDecl>(D)) { // We have a fully initialized TypeDecl. Read its type now. - TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); + TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. if (NamedDeclForTagDecl) cast<TagDecl>(D)->TypedefNameDeclOrQualifier = cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl)); - } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. - ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); + } else if (auto *FD = dyn_cast<FunctionDecl>(D)) { + if (DeferredTypeID) + FD->setType(Reader.GetType(DeferredTypeID)); + // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). @@ -523,8 +571,8 @@ void ASTDeclReader::VisitDecl(Decl *D) { LexicalDCIDForTemplateParmDecl); D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); } else { - DeclContext *SemaDC = ReadDeclAs<DeclContext>(); - DeclContext *LexicalDC = ReadDeclAs<DeclContext>(); + auto *SemaDC = ReadDeclAs<DeclContext>(); + auto *LexicalDC = ReadDeclAs<DeclContext>(); if (!LexicalDC) LexicalDC = SemaDC; DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); @@ -615,7 +663,7 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); TD->setLocStart(ReadSourceLocation()); // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); } ASTDeclReader::RedeclarableResult @@ -667,7 +715,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { case 0: break; case 1: { // ExtInfo - TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); + auto *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info); TD->TypedefNameDeclOrQualifier = Info; break; @@ -698,6 +746,9 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ED->IsScopedUsingClassTag = Record.readInt(); ED->IsFixed = Record.readInt(); + ED->HasODRHash = true; + ED->ODRHash = Record.readInt(); + // If this is a definition subject to the ODR, and we already have a // definition, merge this one into it. if (ED->IsCompleteDefinition && @@ -718,14 +769,15 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); ED->IsCompleteDefinition = false; Reader.mergeDefinitionVisibility(OldDef, ED); + if (OldDef->getODRHash() != ED->getODRHash()) + Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); } else { OldDef = ED; } } - if (EnumDecl *InstED = ReadDeclAs<EnumDecl>()) { - TemplateSpecializationKind TSK = - (TemplateSpecializationKind)Record.readInt(); + if (auto *InstED = ReadDeclAs<EnumDecl>()) { + auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = ReadSourceLocation(); ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK); ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI); @@ -739,12 +791,23 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { RD->setAnonymousStructOrUnion(Record.readInt()); RD->setHasObjectMember(Record.readInt()); RD->setHasVolatileMember(Record.readInt()); + RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt()); + RD->setNonTrivialToPrimitiveCopy(Record.readInt()); + RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); + RD->setParamDestroyedInCallee(Record.readInt()); + RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt()); return Redecl; } void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - VD->setType(Record.readType()); + // For function declarations, defer reading the type in case the function has + // a deduced return type that references an entity declared within the + // function. + if (isa<FunctionDecl>(VD)) + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); + else + VD->setType(Record.readType()); } void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { @@ -759,17 +822,33 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { VisitValueDecl(DD); DD->setInnerLocStart(ReadSourceLocation()); if (Record.readInt()) { // hasExtInfo - DeclaratorDecl::ExtInfo *Info - = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); + auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); ReadQualifierInfo(*Info); DD->DeclInfo = Info; } + QualType TSIType = Record.readType(); + DD->setTypeSourceInfo( + TSIType.isNull() ? nullptr + : Reader.getContext().CreateTypeSourceInfo(TSIType)); } void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); VisitDeclaratorDecl(FD); + // Attach a type to this function. Use the real type if possible, but fall + // back to the type as written if it involves a deduced return type. + if (FD->getTypeSourceInfo() && + FD->getTypeSourceInfo()->getType()->castAs<FunctionType>() + ->getReturnType()->getContainedAutoType()) { + // We'll set up the real type in Visit, once we've finished loading the + // function. + FD->setType(FD->getTypeSourceInfo()->getType()); + } else { + FD->setType(Reader.GetType(DeferredTypeID)); + DeferredTypeID = 0; + } + ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName()); FD->IdentifierNamespace = Record.readInt(); @@ -786,12 +865,14 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->HasWrittenPrototype = Record.readInt(); FD->IsDeleted = Record.readInt(); FD->IsTrivial = Record.readInt(); + FD->IsTrivialForCall = Record.readInt(); FD->IsDefaulted = Record.readInt(); FD->IsExplicitlyDefaulted = Record.readInt(); FD->HasImplicitReturnZero = Record.readInt(); FD->IsConstexpr = Record.readInt(); FD->UsesSEHTry = Record.readInt(); FD->HasSkippedBody = Record.readInt(); + FD->IsMultiVersion = Record.readInt(); FD->IsLateTemplateParsed = Record.readInt(); FD->setCachedLinkage(Linkage(Record.readInt())); FD->EndRangeLoc = ReadSourceLocation(); @@ -808,9 +889,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>()); break; case FunctionDecl::TK_MemberSpecialization: { - FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>(); - TemplateSpecializationKind TSK = - (TemplateSpecializationKind)Record.readInt(); + auto *InstFD = ReadDeclAs<FunctionDecl>(); + auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = ReadSourceLocation(); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); @@ -818,9 +898,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>(); - TemplateSpecializationKind TSK = - (TemplateSpecializationKind)Record.readInt(); + auto *Template = ReadDeclAs<FunctionTemplateDecl>(); + auto TSK = (TemplateSpecializationKind)Record.readInt(); // Template arguments. SmallVector<TemplateArgument, 8> TemplArgs; @@ -833,7 +912,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { if (HasTemplateArgumentsAsWritten) { unsigned NumTemplateArgLocs = Record.readInt(); TemplArgLocs.reserve(NumTemplateArgLocs); - for (unsigned i=0; i != NumTemplateArgLocs; ++i) + for (unsigned i = 0; i != NumTemplateArgLocs; ++i) TemplArgLocs.push_back(Record.readTemplateArgumentLoc()); LAngleLoc = ReadSourceLocation(); @@ -846,7 +925,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { TemplateArgumentList *TemplArgList = TemplateArgumentList::CreateCopy(C, TemplArgs); TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); - for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i) + for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i) TemplArgsInfo.addArgument(TemplArgLocs[i]); FunctionTemplateSpecializationInfo *FTInfo = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, @@ -859,7 +938,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { if (FD->isCanonicalDecl()) { // if canonical add to template's set. // The template that contains the specializations set. It's not safe to // use getCanonicalDecl on Template since it may still be initializing. - FunctionTemplateDecl *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>(); + auto *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>(); // Get the InsertPos by FindNodeOrInsertPos() instead of calling // InsertNode(FTInfo) directly to avoid the getASTContext() call in // FunctionTemplateSpecializationInfo's Profile(). @@ -981,7 +1060,7 @@ ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() { SmallVector<ObjCTypeParamDecl *, 4> typeParams; typeParams.reserve(numParams); for (unsigned i = 0; i != numParams; ++i) { - auto typeParam = ReadDeclAs<ObjCTypeParamDecl>(); + auto *typeParam = ReadDeclAs<ObjCTypeParamDecl>(); if (!typeParam) return nullptr; @@ -1034,7 +1113,7 @@ void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); - TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); mergeRedeclarable(ID, Redecl); ID->TypeParamList = ReadObjCTypeParamList(); @@ -1079,7 +1158,6 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { void ASTDeclReader::ReadObjCDefinitionData( struct ObjCProtocolDecl::DefinitionData &Data) { - unsigned NumProtoRefs = Record.readInt(); SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; ProtoRefs.reserve(NumProtoRefs); @@ -1155,6 +1233,12 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { ProtoLocs.push_back(ReadSourceLocation()); CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), Reader.getContext()); + + // Protocols in the class extension belong to the class. + if (NumProtoRefs > 0 && CD->ClassInterface && CD->IsClassExtension()) + CD->ClassInterface->mergeClassExtensionProtocolList( + (ObjCProtocolDecl *const *)ProtoRefs.data(), NumProtoRefs, + Reader.getContext()); } void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { @@ -1234,7 +1318,7 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { FD->setBitWidth(BW); if (!FD->getDeclName()) { - if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>()) + if (auto *Tmpl = ReadDeclAs<FieldDecl>()) Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); } mergeMergeable(FD); @@ -1272,6 +1356,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.ExceptionVar = Record.readInt(); VD->NonParmVarDeclBits.NRVOVariable = Record.readInt(); VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt(); + VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt(); VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt(); VD->NonParmVarDeclBits.IsInline = Record.readInt(); VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); @@ -1280,7 +1365,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt(); VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt(); } - Linkage VarLinkage = Linkage(Record.readInt()); + auto VarLinkage = Linkage(Record.readInt()); VD->setCachedLinkage(VarLinkage); // Reconstruct the one piece of the IdentifierNamespace that we need. @@ -1316,9 +1401,8 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>()); break; case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo. - VarDecl *Tmpl = ReadDeclAs<VarDecl>(); - TemplateSpecializationKind TSK = - (TemplateSpecializationKind)Record.readInt(); + auto *Tmpl = ReadDeclAs<VarDecl>(); + auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = ReadSourceLocation(); Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); mergeRedeclarable(VD, Redecl); @@ -1357,7 +1441,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { void ASTDeclReader::VisitDecompositionDecl(DecompositionDecl *DD) { VisitVarDecl(DD); - BindingDecl **BDs = DD->getTrailingObjects<BindingDecl*>(); + auto **BDs = DD->getTrailingObjects<BindingDecl *>(); for (unsigned I = 0; I != DD->NumBindings; ++I) BDs[I] = ReadDeclAs<BindingDecl>(); } @@ -1393,7 +1477,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { SmallVector<BlockDecl::Capture, 16> captures; captures.reserve(numCaptures); for (unsigned i = 0; i != numCaptures; ++i) { - VarDecl *decl = ReadDeclAs<VarDecl>(); + auto *decl = ReadDeclAs<VarDecl>(); unsigned flags = Record.readInt(); bool byRef = (flags & 1); bool nested = (flags & 2); @@ -1460,7 +1544,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. - NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace)); + auto *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace)); if (!Record.isModule()) D->setAnonymousNamespace(Anon); } @@ -1483,7 +1567,7 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { ReadDeclarationNameLoc(D->DNLoc, D->getDeclName()); D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>()); D->setTypename(Record.readInt()); - if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>()) + if (auto *Pattern = ReadDeclAs<NamedDecl>()) Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); mergeMergeable(D); } @@ -1491,7 +1575,7 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) { VisitNamedDecl(D); D->InstantiatedFrom = ReadDeclAs<NamedDecl>(); - NamedDecl **Expansions = D->getTrailingObjects<NamedDecl*>(); + auto **Expansions = D->getTrailingObjects<NamedDecl *>(); for (unsigned I = 0; I != D->NumExpansions; ++I) Expansions[I] = ReadDeclAs<NamedDecl>(); mergeMergeable(D); @@ -1500,9 +1584,10 @@ void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) { void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); - D->setTargetDecl(ReadDeclAs<NamedDecl>()); + D->Underlying = ReadDeclAs<NamedDecl>(); + D->IdentifierNamespace = Record.readInt(); D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(); - UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(); + auto *Pattern = ReadDeclAs<UsingShadowDecl>(); if (Pattern) Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); mergeRedeclarable(D, Redecl); @@ -1554,7 +1639,9 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.Polymorphic = Record.readInt(); Data.Abstract = Record.readInt(); Data.IsStandardLayout = Record.readInt(); - Data.HasNoNonEmptyBases = Record.readInt(); + Data.IsCXX11StandardLayout = Record.readInt(); + Data.HasBasesWithFields = Record.readInt(); + Data.HasBasesWithNonStaticDataMembers = Record.readInt(); Data.HasPrivateFields = Record.readInt(); Data.HasProtectedFields = Record.readInt(); Data.HasPublicFields = Record.readInt(); @@ -1575,11 +1662,12 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.DefaultedMoveAssignmentIsDeleted = Record.readInt(); Data.DefaultedDestructorIsDeleted = Record.readInt(); Data.HasTrivialSpecialMembers = Record.readInt(); + Data.HasTrivialSpecialMembersForCall = Record.readInt(); Data.DeclaredNonTrivialSpecialMembers = Record.readInt(); + Data.DeclaredNonTrivialSpecialMembersForCall = Record.readInt(); Data.HasIrrelevantDestructor = Record.readInt(); Data.HasConstexprNonCopyMoveConstructor = Record.readInt(); Data.HasDefaultedDefaultConstructor = Record.readInt(); - Data.CanPassInRegisters = Record.readInt(); Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt(); Data.HasConstexprDefaultConstructor = Record.readInt(); Data.HasNonLiteralTypeFieldsOrBases = Record.readInt(); @@ -1610,9 +1698,9 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.FirstFriend = ReadDeclID(); if (Data.IsLambda) { - typedef LambdaCapture Capture; - CXXRecordDecl::LambdaDefinitionData &Lambda - = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); + using Capture = LambdaCapture; + + auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); Lambda.Dependent = Record.readInt(); Lambda.IsGenericLambda = Record.readInt(); Lambda.CaptureDefault = Record.readInt(); @@ -1627,7 +1715,7 @@ void ASTDeclReader::ReadCXXDefinitionData( for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { SourceLocation Loc = ReadSourceLocation(); bool IsImplicit = Record.readInt(); - LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record.readInt()); + auto Kind = static_cast<LambdaCaptureKind>(Record.readInt()); switch (Kind) { case LCK_StarThis: case LCK_This: @@ -1636,7 +1724,7 @@ void ASTDeclReader::ReadCXXDefinitionData( break; case LCK_ByCopy: case LCK_ByRef: - VarDecl *Var = ReadDeclAs<VarDecl>(); + auto *Var = ReadDeclAs<VarDecl>(); SourceLocation EllipsisLoc = ReadSourceLocation(); *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); break; @@ -1692,7 +1780,9 @@ void ASTDeclReader::MergeDefinitionData( MATCH_FIELD(Polymorphic) MATCH_FIELD(Abstract) MATCH_FIELD(IsStandardLayout) - MATCH_FIELD(HasNoNonEmptyBases) + MATCH_FIELD(IsCXX11StandardLayout) + MATCH_FIELD(HasBasesWithFields) + MATCH_FIELD(HasBasesWithNonStaticDataMembers) MATCH_FIELD(HasPrivateFields) MATCH_FIELD(HasProtectedFields) MATCH_FIELD(HasPublicFields) @@ -1713,11 +1803,12 @@ void ASTDeclReader::MergeDefinitionData( MATCH_FIELD(DefaultedMoveAssignmentIsDeleted) MATCH_FIELD(DefaultedDestructorIsDeleted) OR_FIELD(HasTrivialSpecialMembers) + OR_FIELD(HasTrivialSpecialMembersForCall) OR_FIELD(DeclaredNonTrivialSpecialMembers) + OR_FIELD(DeclaredNonTrivialSpecialMembersForCall) MATCH_FIELD(HasIrrelevantDestructor) OR_FIELD(HasConstexprNonCopyMoveConstructor) OR_FIELD(HasDefaultedDefaultConstructor) - MATCH_FIELD(CanPassInRegisters) MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr) OR_FIELD(HasConstexprDefaultConstructor) MATCH_FIELD(HasNonLiteralTypeFieldsOrBases) @@ -1775,29 +1866,31 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { else DD = new (C) struct CXXRecordDecl::DefinitionData(D); + CXXRecordDecl *Canon = D->getCanonicalDecl(); + // Set decl definition data before reading it, so that during deserialization + // when we read CXXRecordDecl, it already has definition data and we don't + // set fake one. + if (!Canon->DefinitionData) + Canon->DefinitionData = DD; + D->DefinitionData = Canon->DefinitionData; ReadCXXDefinitionData(*DD, D); - // We might already have a definition for this record. This can happen either - // because we're reading an update record, or because we've already done some - // merging. Either way, just merge into it. - CXXRecordDecl *Canon = D->getCanonicalDecl(); - if (Canon->DefinitionData) { + // We might already have a different definition for this record. This can + // happen either because we're reading an update record, or because we've + // already done some merging. Either way, just merge into it. + if (Canon->DefinitionData != DD) { MergeDefinitionData(Canon, std::move(*DD)); - D->DefinitionData = Canon->DefinitionData; return; } // Mark this declaration as being a definition. D->IsCompleteDefinition = true; - D->DefinitionData = DD; // If this is not the first declaration or is an update record, we can have // other redeclarations already. Make a note that we need to propagate the // DefinitionData pointer onto them. - if (Update || Canon != D) { - Canon->DefinitionData = D->DefinitionData; + if (Update || Canon != D) Reader.PendingDefinitions.insert(D); - } } ASTDeclReader::RedeclarableResult @@ -1817,7 +1910,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { break; case CXXRecTemplate: { // Merged when we merge the template. - ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>(); + auto *Template = ReadDeclAs<ClassTemplateDecl>(); D->TemplateOrInstantiation = Template; if (!Template->getTemplatedDecl()) { // We've not actually loaded the ClassTemplateDecl yet, because we're @@ -1826,14 +1919,13 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // // 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; + DeferredTypeID = 0; } break; } case CXXRecMemberSpecialization: { - CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(); - TemplateSpecializationKind TSK = - (TemplateSpecializationKind)Record.readInt(); + auto *RD = ReadDeclAs<CXXRecordDecl>(); + auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = ReadSourceLocation(); MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK); MSI->setPointOfInstantiation(POI); @@ -1877,7 +1969,7 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { while (NumOverridenMethods--) { // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, // MD may be initializing. - if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>()) + if (auto *MD = ReadDeclAs<CXXMethodDecl>()) Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl()); } } else { @@ -1904,7 +1996,7 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>()) { - auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl()); + CXXDestructorDecl *Canon = D->getCanonicalDecl(); auto *ThisArg = Record.readExpr(); // FIXME: Check consistency if we have an old and new operator delete. if (!Canon->OperatorDelete) { @@ -1922,7 +2014,7 @@ void ASTDeclReader::VisitImportDecl(ImportDecl *D) { VisitDecl(D); D->ImportedAndComplete.setPointer(readModule()); D->ImportedAndComplete.setInt(Record.readInt()); - SourceLocation *StoredLocs = D->getTrailingObjects<SourceLocation>(); + auto *StoredLocs = D->getTrailingObjects<SourceLocation>(); for (unsigned I = 0, N = Record.back(); I != N; ++I) StoredLocs[I] = ReadSourceLocation(); Record.skipInts(1); // The number of stored source locations. @@ -1965,7 +2057,7 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); DeclID PatternID = ReadDeclID(); - NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); + auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); // FIXME handle associated constraints D->init(TemplatedDecl, TemplateParams); @@ -1989,8 +2081,7 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { // If this is the first declaration of the template, fill in the information // for the 'common' pointer. if (ThisDeclID == Redecl.getFirstID()) { - if (RedeclarableTemplateDecl *RTD - = ReadDeclAs<RedeclarableTemplateDecl>()) { + if (auto *RTD = ReadDeclAs<RedeclarableTemplateDecl>()) { assert(RTD->getKind() == D->getKind() && "InstantiatedFromMemberTemplate kind mismatch"); D->setInstantiatedFromMemberTemplate(RTD); @@ -2058,15 +2149,15 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( ASTContext &C = Reader.getContext(); if (Decl *InstD = ReadDecl()) { - if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { + if (auto *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { D->SpecializedTemplate = CTD; } else { SmallVector<TemplateArgument, 8> TemplArgs; Record.readTemplateArgumentList(TemplArgs); TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(C, TemplArgs); - ClassTemplateSpecializationDecl::SpecializedPartialSpecialization *PS - = new (C) ClassTemplateSpecializationDecl:: + auto *PS = + new (C) ClassTemplateSpecializationDecl:: SpecializedPartialSpecialization(); PS->PartialSpecialization = cast<ClassTemplatePartialSpecializationDecl>(InstD); @@ -2083,12 +2174,11 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( bool writtenAsCanonicalDecl = Record.readInt(); if (writtenAsCanonicalDecl) { - ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(); + auto *CanonPattern = ReadDeclAs<ClassTemplateDecl>(); if (D->isCanonicalDecl()) { // It's kept in the folding set. // Set this as, or find, the canonical declaration for this specialization ClassTemplateSpecializationDecl *CanonSpec; - if (ClassTemplatePartialSpecializationDecl *Partial = - dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { + if (auto *Partial = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations .GetOrInsertNode(Partial); } else { @@ -2114,8 +2204,8 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( // Explicit info. if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) { - ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo - = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; + auto *ExplicitInfo = + new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; ExplicitInfo->TypeAsWritten = TyInfo; ExplicitInfo->ExternLoc = ReadSourceLocation(); ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(); @@ -2169,14 +2259,14 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( ASTContext &C = Reader.getContext(); if (Decl *InstD = ReadDecl()) { - if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) { + if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) { D->SpecializedTemplate = VTD; } else { SmallVector<TemplateArgument, 8> TemplArgs; Record.readTemplateArgumentList(TemplArgs); TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy( C, TemplArgs); - VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS = + auto *PS = new (C) VarTemplateSpecializationDecl::SpecializedPartialSpecialization(); PS->PartialSpecialization = @@ -2188,7 +2278,7 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( // Explicit info. if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) { - VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo = + auto *ExplicitInfo = new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; ExplicitInfo->TypeAsWritten = TyInfo; ExplicitInfo->ExternLoc = ReadSourceLocation(); @@ -2205,11 +2295,10 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( bool writtenAsCanonicalDecl = Record.readInt(); if (writtenAsCanonicalDecl) { - VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(); + auto *CanonPattern = ReadDeclAs<VarTemplateDecl>(); if (D->isCanonicalDecl()) { // It's kept in the folding set. // FIXME: If it's already present, merge it. - if (VarTemplatePartialSpecializationDecl *Partial = - dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { + if (auto *Partial = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { CanonPattern->getCommonPtr()->PartialSpecializations .GetOrInsertNode(Partial); } else { @@ -2276,8 +2365,7 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { D->setDepth(Record.readInt()); D->setPosition(Record.readInt()); if (D->isExpandedParameterPack()) { - TemplateParameterList **Data = - D->getTrailingObjects<TemplateParameterList *>(); + auto **Data = D->getTrailingObjects<TemplateParameterList *>(); for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); I != N; ++I) Data[I] = Record.readTemplateParameterList(); @@ -2351,7 +2439,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { (void)ReadDecl(); } - T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID)); + auto *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID)); if (FirstDecl != D) { // We delay loading of the redeclaration chain to avoid deeply nested calls. // We temporarily set the first (canonical) declaration as the previous one @@ -2361,7 +2449,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { D->First = FirstDecl->getCanonicalDecl(); } - T *DAsT = static_cast<T*>(D); + auto *DAsT = static_cast<T *>(D); // Note that we need to load local redeclarations of this decl and build a // decl chain for them. This must happen *after* we perform the preloading @@ -2373,7 +2461,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { return RedeclarableResult(MergeWith, FirstDeclID, IsKeyDecl); } -/// \brief Attempts to merge the given declaration (D) with another declaration +/// Attempts to merge the given declaration (D) with another declaration /// of the same entity. template<typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, @@ -2387,7 +2475,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, if (!DBase->isFirstDecl()) return; - T *D = static_cast<T*>(DBase); + auto *D = static_cast<T *>(DBase); if (auto *Existing = Redecl.getKnownMergeTarget()) // We already know of an existing declaration we should merge with. @@ -2397,7 +2485,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); } -/// \brief "Cast" to type T, asserting if we don't have an implicit conversion. +/// "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; } @@ -2405,7 +2493,7 @@ template<typename T> static T assert_cast(...) { llvm_unreachable("bad assert_cast"); } -/// \brief Merge together the pattern declarations from two template +/// Merge together the pattern declarations from two template /// declarations. void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, @@ -2447,13 +2535,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, llvm_unreachable("merged an unknown kind of redeclarable template"); } -/// \brief Attempts to merge the given declaration (D) with another declaration +/// Attempts to merge the given declaration (D) with another declaration /// of the same entity. template<typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, RedeclarableResult &Redecl, DeclID TemplatePatternID) { - T *D = static_cast<T*>(DBase); + auto *D = static_cast<T *>(DBase); T *ExistingCanon = Existing->getCanonicalDecl(); T *DCanon = D->getCanonicalDecl(); if (ExistingCanon != DCanon) { @@ -2487,7 +2575,21 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, } } -/// \brief Attempts to merge the given declaration (D) with another declaration +/// ODR-like semantics for C/ObjC allow us to merge tag types and a structural +/// check in Sema guarantees the types can be merged (see C11 6.2.7/1 or C89 +/// 6.1.2.6/1). Although most merging is done in Sema, we need to guarantee +/// that some types are mergeable during deserialization, otherwise name +/// lookup fails. This is the case for EnumConstantDecl. +static bool allowODRLikeMergeInC(NamedDecl *ND) { + if (!ND) + return false; + // TODO: implement merge for other necessary decls. + if (isa<EnumConstantDecl>(ND)) + return true; + return false; +} + +/// Attempts to merge the given declaration (D) with another declaration /// of the same entity, for the case where the entity is not actually /// redeclarable. This happens, for instance, when merging the fields of /// identical class definitions from two different modules. @@ -2497,10 +2599,12 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) { if (!Reader.getContext().getLangOpts().Modules) return; - // ODR-based merging is only performed in C++. In C, identically-named things - // in different translation units are not redeclarations (but may still have - // compatible types). - if (!Reader.getContext().getLangOpts().CPlusPlus) + // ODR-based merging is performed in C++ and in some cases (tag types) in C. + // Note that C identically-named things in different translation units are + // not redeclarations, but may still have compatible types, where ODR-like + // semantics may apply. + if (!Reader.getContext().getLangOpts().CPlusPlus && + !allowODRLikeMergeInC(dyn_cast<NamedDecl>(static_cast<T*>(D)))) return; if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) @@ -2538,11 +2642,11 @@ void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { // Attribute Reading //===----------------------------------------------------------------------===// -/// \brief Reads attributes from the current stream position. +/// Reads attributes from the current stream position. void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { for (unsigned i = 0, e = Record.readInt(); i != e; ++i) { Attr *New = nullptr; - attr::Kind Kind = (attr::Kind)Record.readInt(); + auto Kind = (attr::Kind)Record.readInt(); SourceRange Range = Record.readSourceRange(); ASTContext &Context = getContext(); @@ -2557,7 +2661,7 @@ void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { // ASTReader Implementation //===----------------------------------------------------------------------===// -/// \brief Note that we have loaded the declaration with the given +/// Note that we have loaded the declaration with the given /// Index. /// /// This routine notes that this declaration has already been loaded, @@ -2568,8 +2672,7 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) { DeclsLoaded[Index] = D; } - -/// \brief Determine whether the consumer will be interested in seeing +/// Determine whether the consumer will be interested in seeing /// this declaration (via HandleTopLevelDecl). /// /// This routine should return true for anything that might affect @@ -2597,10 +2700,10 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { return true; if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isFunctionOrMethod(); - if (VarDecl *Var = dyn_cast<VarDecl>(D)) + if (const auto *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && Var->isThisDeclarationADefinition() == VarDecl::Definition; - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) + if (const auto *Func = dyn_cast<FunctionDecl>(D)) return Func->doesThisDeclarationHaveABody() || HasBody; if (auto *ES = D->getASTContext().getExternalSource()) @@ -2610,7 +2713,7 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { return false; } -/// \brief Get the correct cursor and offset for loading a declaration. +/// Get the correct cursor and offset for loading a declaration. ASTReader::RecordLocation ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) { GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); @@ -2623,8 +2726,7 @@ ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) { } ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) { - ContinuousRangeMap<uint64_t, ModuleFile*, 4>::iterator I - = GlobalBitOffsetsMap.find(GlobalOffset); + auto I = GlobalBitOffsetsMap.find(GlobalOffset); assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map"); return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset); @@ -2637,26 +2739,26 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { static bool isSameTemplateParameterList(const TemplateParameterList *X, const TemplateParameterList *Y); -/// \brief Determine whether two template parameters are similar enough +/// Determine whether two template parameters are similar enough /// that they may be used in declarations of the same template. static bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) { if (X->getKind() != Y->getKind()) return false; - if (const TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) { - const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y); + if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) { + const auto *TY = cast<TemplateTypeParmDecl>(Y); return TX->isParameterPack() == TY->isParameterPack(); } - if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) { - const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y); + if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) { + const auto *TY = cast<NonTypeTemplateParmDecl>(Y); return TX->isParameterPack() == TY->isParameterPack() && TX->getASTContext().hasSameType(TX->getType(), TY->getType()); } - const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X); - const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y); + const auto *TX = cast<TemplateTemplateParmDecl>(X); + const auto *TY = cast<TemplateTemplateParmDecl>(Y); return TX->isParameterPack() == TY->isParameterPack() && isSameTemplateParameterList(TX->getTemplateParameters(), TY->getTemplateParameters()); @@ -2709,7 +2811,7 @@ static bool isSameQualifier(const NestedNameSpecifier *X, return !PX && !PY; } -/// \brief Determine whether two template parameter lists are similar enough +/// Determine whether two template parameter lists are similar enough /// that they may be used in declarations of the same template. static bool isSameTemplateParameterList(const TemplateParameterList *X, const TemplateParameterList *Y) { @@ -2762,7 +2864,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A, return true; } -/// \brief Determine whether the two declarations refer to the same entity. +/// Determine whether the two declarations refer to the same entity. static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); @@ -2770,14 +2872,18 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return true; // Must be in the same context. - if (!X->getDeclContext()->getRedeclContext()->Equals( - Y->getDeclContext()->getRedeclContext())) + // + // Note that we can't use DeclContext::Equals here, because the DeclContexts + // could be two different declarations of the same function. (We will fix the + // semantic DC to refer to the primary definition after merging.) + if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()), + cast<Decl>(Y->getDeclContext()->getRedeclContext()))) return false; // Two typedefs refer to the same entity if they have the same underlying // type. - if (TypedefNameDecl *TypedefX = dyn_cast<TypedefNameDecl>(X)) - if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y)) + if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X)) + if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y)) return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), TypedefY->getUnderlyingType()); @@ -2796,8 +2902,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } // Compatible tags match. - if (TagDecl *TagX = dyn_cast<TagDecl>(X)) { - TagDecl *TagY = cast<TagDecl>(Y); + if (const auto *TagX = dyn_cast<TagDecl>(X)) { + const auto *TagY = cast<TagDecl>(Y); return (TagX->getTagKind() == TagY->getTagKind()) || ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class || TagX->getTagKind() == TTK_Interface) && @@ -2808,28 +2914,51 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { // Functions with the same type and linkage match. // FIXME: This needs to cope with merging of prototyped/non-prototyped // functions, etc. - if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { - FunctionDecl *FuncY = cast<FunctionDecl>(Y); - if (CXXConstructorDecl *CtorX = dyn_cast<CXXConstructorDecl>(X)) { - CXXConstructorDecl *CtorY = cast<CXXConstructorDecl>(Y); + if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) { + const auto *FuncY = cast<FunctionDecl>(Y); + if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) { + const auto *CtorY = cast<CXXConstructorDecl>(Y); if (CtorX->getInheritedConstructor() && !isSameEntity(CtorX->getInheritedConstructor().getConstructor(), CtorY->getInheritedConstructor().getConstructor())) return false; } + + if (FuncX->isMultiVersion() != FuncY->isMultiVersion()) + return false; + + // Multiversioned functions with different feature strings are represented + // as separate declarations. + if (FuncX->isMultiVersion()) { + const auto *TAX = FuncX->getAttr<TargetAttr>(); + const auto *TAY = FuncY->getAttr<TargetAttr>(); + assert(TAX && TAY && "Multiversion Function without target attribute"); + + if (TAX->getFeaturesStr() != TAY->getFeaturesStr()) + return false; + } + ASTContext &C = FuncX->getASTContext(); - if (!C.hasSameType(FuncX->getType(), FuncY->getType())) { + auto GetTypeAsWritten = [](const FunctionDecl *FD) { + // Map to the first declaration that we've already merged into this one. + // The TSI of redeclarations might not match (due to calling conventions + // being inherited onto the type but not the TSI), but the TSI type of + // the first declaration of the function should match across modules. + FD = FD->getCanonicalDecl(); + return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType() + : FD->getType(); + }; + QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY); + if (!C.hasSameType(XT, YT)) { // We can get functions with different types on the redecl chain in C++17 // if they have differing exception specifications and at least one of // the excpetion specs is unresolved. - // FIXME: Do we need to check for C++14 deduced return types here too? - auto *XFPT = FuncX->getType()->getAs<FunctionProtoType>(); - auto *YFPT = FuncY->getType()->getAs<FunctionProtoType>(); + auto *XFPT = XT->getAs<FunctionProtoType>(); + auto *YFPT = YT->getAs<FunctionProtoType>(); if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT && (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && - C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(), - FuncY->getType())) + C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT)) return true; return false; } @@ -2838,8 +2967,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } // Variables with the same type and linkage match. - if (VarDecl *VarX = dyn_cast<VarDecl>(X)) { - VarDecl *VarY = cast<VarDecl>(Y); + if (const auto *VarX = dyn_cast<VarDecl>(X)) { + const auto *VarY = cast<VarDecl>(Y); if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) { ASTContext &C = VarX->getASTContext(); if (C.hasSameType(VarX->getType(), VarY->getType())) @@ -2861,15 +2990,15 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } // Namespaces with the same name and inlinedness match. - if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) { - NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y); + if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) { + const auto *NamespaceY = cast<NamespaceDecl>(Y); return NamespaceX->isInline() == NamespaceY->isInline(); } // Identical template names and kinds match if their template parameter lists // and patterns match. - if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) { - TemplateDecl *TemplateY = cast<TemplateDecl>(Y); + if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) { + const auto *TemplateY = cast<TemplateDecl>(Y); return isSameEntity(TemplateX->getTemplatedDecl(), TemplateY->getTemplatedDecl()) && isSameTemplateParameterList(TemplateX->getTemplateParameters(), @@ -2877,15 +3006,15 @@ 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); + if (const auto *FDX = dyn_cast<FieldDecl>(X)) { + const auto *FDY = cast<FieldDecl>(Y); // FIXME: Also check the bitwidth is odr-equivalent, if any. return X->getASTContext().hasSameType(FDX->getType(), FDY->getType()); } // Indirect fields with the same target field match. - if (auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) { - auto *IFDY = cast<IndirectFieldDecl>(Y); + if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) { + const auto *IFDY = cast<IndirectFieldDecl>(Y); return IFDX->getAnonField()->getCanonicalDecl() == IFDY->getAnonField()->getCanonicalDecl(); } @@ -2896,32 +3025,32 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return true; // Using shadow declarations with the same target match. - if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) { - UsingShadowDecl *USY = cast<UsingShadowDecl>(Y); + if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) { + const auto *USY = cast<UsingShadowDecl>(Y); return USX->getTargetDecl() == USY->getTargetDecl(); } // Using declarations with the same qualifier match. (We already know that // the name matches.) - if (auto *UX = dyn_cast<UsingDecl>(X)) { - auto *UY = cast<UsingDecl>(Y); + if (const auto *UX = dyn_cast<UsingDecl>(X)) { + const auto *UY = cast<UsingDecl>(Y); return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && UX->hasTypename() == UY->hasTypename() && UX->isAccessDeclaration() == UY->isAccessDeclaration(); } - if (auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) { - auto *UY = cast<UnresolvedUsingValueDecl>(Y); + if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) { + const auto *UY = cast<UnresolvedUsingValueDecl>(Y); return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && UX->isAccessDeclaration() == UY->isAccessDeclaration(); } - if (auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) + if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) return isSameQualifier( UX->getQualifier(), cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier()); // Namespace alias definitions with the same target match. - if (auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) { - auto *NAY = cast<NamespaceAliasDecl>(Y); + if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) { + const auto *NAY = cast<NamespaceAliasDecl>(Y); return NAX->getNamespace()->Equals(NAY->getNamespace()); } @@ -2932,10 +3061,10 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { /// looking for declarations to merge. DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, DeclContext *DC) { - if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC)) + if (auto *ND = dyn_cast<NamespaceDecl>(DC)) return ND->getOriginalNamespace(); - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { + if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { // Try to dig out the definition. auto *DD = RD->DefinitionData; if (!DD) @@ -2959,7 +3088,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, return DD->Definition; } - if (EnumDecl *ED = dyn_cast<EnumDecl>(DC)) + if (auto *ED = dyn_cast<EnumDecl>(DC)) return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : nullptr; @@ -3021,23 +3150,50 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found, return nullptr; } +/// Find the declaration to use to populate the anonymous declaration table +/// for the given lexical DeclContext. We only care about finding local +/// definitions of the context; we'll merge imported ones as we go. +DeclContext * +ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { + // For classes, we track the definition as we merge. + if (auto *RD = dyn_cast<CXXRecordDecl>(LexicalDC)) { + auto *DD = RD->getCanonicalDecl()->DefinitionData; + return DD ? DD->Definition : nullptr; + } + + // For anything else, walk its merged redeclarations looking for a definition. + // Note that we can't just call getDefinition here because the redeclaration + // chain isn't wired up. + for (auto *D : merged_redecls(cast<Decl>(LexicalDC))) { + if (auto *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isThisDeclarationADefinition()) + return FD; + if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) + if (MD->isThisDeclarationADefinition()) + return MD; + } + + // No merged definition yet. + return nullptr; +} + NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index) { // If the lexical context has been merged, look into the now-canonical // definition. - if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) - DC = Merged; + auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl(); // If we've seen this before, return the canonical declaration. - auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; if (Index < Previous.size() && Previous[Index]) return Previous[Index]; // If this is the first time, but we have parsed a declaration of the context, // build the anonymous declaration list from the parsed declaration. - if (!cast<Decl>(DC)->isFromASTFile()) { - numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) { + auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC); + if (PrimaryDC && !cast<Decl>(PrimaryDC)->isFromASTFile()) { + numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) { if (Previous.size() == Number) Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl())); else @@ -3051,10 +3207,9 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index, NamedDecl *D) { - if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) - DC = Merged; + auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl(); - auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; if (Index >= Previous.size()) Previous.resize(Index + 1); if (!Previous[Index]) @@ -3102,12 +3257,10 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // cause additional lookups here. class UpToDateIdentifierRAII { IdentifierInfo *II; - bool WasOutToDate; + bool WasOutToDate = false; public: - explicit UpToDateIdentifierRAII(IdentifierInfo *II) - : II(II), WasOutToDate(false) - { + explicit UpToDateIdentifierRAII(IdentifierInfo *II) : II(II) { if (II) { WasOutToDate = II->isOutOfDate(); if (WasOutToDate) @@ -3160,6 +3313,7 @@ template<typename DeclT> Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) { return D->RedeclLink.getLatestNotUpdated(); } + Decl *ASTDeclReader::getMostRecentDeclImpl(...) { llvm_unreachable("getMostRecentDecl on non-redeclarable declaration"); } @@ -3190,12 +3344,13 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, } namespace clang { + template<> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable<VarDecl> *D, Decl *Previous, Decl *Canon) { - VarDecl *VD = static_cast<VarDecl*>(D); - VarDecl *PrevVD = cast<VarDecl>(Previous); + auto *VD = static_cast<VarDecl *>(D); + auto *PrevVD = cast<VarDecl>(Previous); D->RedeclLink.setPrevious(PrevVD); D->First = PrevVD->First; @@ -3217,8 +3372,8 @@ template<> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable<FunctionDecl> *D, Decl *Previous, Decl *Canon) { - FunctionDecl *FD = static_cast<FunctionDecl*>(D); - FunctionDecl *PrevFD = cast<FunctionDecl>(Previous); + auto *FD = static_cast<FunctionDecl *>(D); + auto *PrevFD = cast<FunctionDecl>(Previous); FD->RedeclLink.setPrevious(PrevFD); FD->First = PrevFD->First; @@ -3257,7 +3412,8 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, std::make_pair(Canon, IsUnresolved ? PrevFD : FD)); } } -} // end namespace clang + +} // namespace clang void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) { llvm_unreachable("attachPreviousDecl on non-redeclarable declaration"); @@ -3326,7 +3482,7 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, // If the declaration declares a template, it may inherit default arguments // from the previous declaration. - if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) + if (auto *TD = dyn_cast<TemplateDecl>(D)) inheritDefaultTemplateArguments(Reader.getContext(), cast<TemplateDecl>(Previous), TD); } @@ -3335,6 +3491,7 @@ 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"); } @@ -3356,6 +3513,7 @@ template<typename DeclT> void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) { D->RedeclLink.markIncomplete(); } + void ASTDeclReader::markIncompleteDeclChainImpl(...) { llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration"); } @@ -3371,7 +3529,7 @@ void ASTReader::markIncompleteDeclChain(Decl *D) { } } -/// \brief Read the declaration at the given offset from the AST file. +/// Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned Index = ID - NUM_PREDEF_DECL_IDS; SourceLocation DeclLoc; @@ -3639,7 +3797,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // If this declaration is also a declaration context, get the // offsets for its tables of lexical and visible declarations. - if (DeclContext *DC = dyn_cast<DeclContext>(D)) { + if (auto *DC = dyn_cast<DeclContext>(D)) { std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); if (Offsets.first && ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) @@ -3655,7 +3813,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { PendingUpdateRecord(ID, D, /*JustLoaded=*/true)); // Load the categories after recursive loading is finished. - if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) + if (auto *Class = dyn_cast<ObjCInterfaceDecl>(D)) // If we already have a definition when deserializing the ObjCInterfaceDecl, // we put the Decl in PendingDefinitions so we can pull the categories here. if (Class->isThisDeclarationADefinition() || @@ -3706,7 +3864,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); - llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; + SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); @@ -3763,7 +3921,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { PendingVisibleUpdates.erase(I); auto *DC = cast<DeclContext>(D)->getPrimaryContext(); - for (const PendingVisibleUpdate &Update : VisibleUpdates) + for (const auto &Update : VisibleUpdates) Lookups[DC].Table.add( Update.Mod, Update.Data, reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod)); @@ -3812,13 +3970,14 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { } namespace { - /// \brief Given an ObjC interface, goes through the modules and links to the + + /// Given an ObjC interface, goes through the modules and links to the /// interface all the categories for it. class ObjCCategoriesVisitor { ASTReader &Reader; ObjCInterfaceDecl *Interface; llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized; - ObjCCategoryDecl *Tail; + ObjCCategoryDecl *Tail = nullptr; llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; serialization::GlobalDeclID InterfaceID; unsigned PreviousGeneration; @@ -3868,10 +4027,8 @@ namespace { llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, serialization::GlobalDeclID InterfaceID, unsigned PreviousGeneration) - : Reader(Reader), Interface(Interface), Deserialized(Deserialized), - Tail(nullptr), InterfaceID(InterfaceID), - PreviousGeneration(PreviousGeneration) - { + : Reader(Reader), Interface(Interface), Deserialized(Deserialized), + InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) { // Populate the name -> category map with the set of known categories. for (auto *Cat : Interface->known_categories()) { if (Cat->getDeclName()) @@ -3920,7 +4077,8 @@ namespace { return true; } }; -} // end anonymous namespace + +} // namespace void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D, @@ -3973,13 +4131,13 @@ void ASTDeclReader::UpdateDecl(Decl *D, break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { - NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(); + auto *Anon = ReadDeclAs<NamespaceDecl>(); // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. if (!Record.isModule()) { - if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) + if (auto *TU = dyn_cast<TranslationUnitDecl>(D)) TU->setAnonymousNamespace(Anon); else cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon); @@ -3988,7 +4146,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, } case UPD_CXX_ADDED_VAR_DEFINITION: { - VarDecl *VD = cast<VarDecl>(D); + auto *VD = cast<VarDecl>(D); VD->NonParmVarDeclBits.IsInline = Record.readInt(); VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); uint64_t Val = Record.readInt(); @@ -4005,8 +4163,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, case UPD_CXX_POINT_OF_INSTANTIATION: { SourceLocation POI = Record.readSourceLocation(); - if (VarTemplateSpecializationDecl *VTSD = - dyn_cast<VarTemplateSpecializationDecl>(D)) { + if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) { VTSD->setPointOfInstantiation(POI); } else if (auto *VD = dyn_cast<VarDecl>(D)) { VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); @@ -4023,12 +4180,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, } case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: { - auto Param = cast<ParmVarDecl>(D); + auto *Param = cast<ParmVarDecl>(D); // We have to read the default argument regardless of whether we use it // so that hypothetical further update records aren't messed up. // TODO: Add a function to skip over the next expr record. - auto DefaultArg = Record.readExpr(); + auto *DefaultArg = Record.readExpr(); // Only apply the update if the parameter still has an uninstantiated // default argument. @@ -4038,8 +4195,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, } case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: { - auto FD = cast<FieldDecl>(D); - auto DefaultInit = Record.readExpr(); + auto *FD = cast<FieldDecl>(D); + auto *DefaultInit = Record.readExpr(); // Only apply the update if the field still has an uninstantiated // default member initializer. @@ -4055,7 +4212,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, } case UPD_CXX_ADDED_FUNCTION_DEFINITION: { - FunctionDecl *FD = cast<FunctionDecl>(D); + auto *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. @@ -4082,6 +4239,9 @@ void ASTDeclReader::UpdateDecl(Decl *D, bool HadRealDefinition = OldDD && (OldDD->Definition != RD || !Reader.PendingFakeDefinitionData.count(OldDD)); + RD->setParamDestroyedInCallee(Record.readInt()); + RD->setArgPassingRestrictions( + (RecordDecl::ArgPassingKind)Record.readInt()); ReadCXXRecordDefinition(RD, /*Update*/true); // Visible update is handled separately. @@ -4098,13 +4258,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, MSInfo->setTemplateSpecializationKind(TSK); MSInfo->setPointOfInstantiation(POI); } else { - ClassTemplateSpecializationDecl *Spec = - cast<ClassTemplateSpecializationDecl>(RD); + auto *Spec = cast<ClassTemplateSpecializationDecl>(RD); Spec->setTemplateSpecializationKind(TSK); Spec->setPointOfInstantiation(POI); if (Record.readInt()) { - auto PartialSpec = + auto *PartialSpec = ReadDeclAs<ClassTemplatePartialSpecializationDecl>(); SmallVector<TemplateArgument, 8> TemplArgs; Record.readTemplateArgumentList(TemplArgs); @@ -4177,18 +4336,17 @@ void ASTDeclReader::UpdateDecl(Decl *D, QualType DeducedResultType = Record.readType(); for (auto *Redecl : merged_redecls(D)) { // FIXME: If the return type is already deduced, check that it matches. - FunctionDecl *FD = cast<FunctionDecl>(Redecl); + auto *FD = cast<FunctionDecl>(Redecl); Reader.getContext().adjustDeducedFunctionResultType(FD, DeducedResultType); } break; } - case UPD_DECL_MARKED_USED: { + case UPD_DECL_MARKED_USED: // Maintain AST consistency: any later redeclarations are used too. D->markUsed(Reader.getContext()); break; - } case UPD_MANGLING_NUMBER: Reader.getContext().setManglingNumber(cast<NamedDecl>(D), diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h index 2b92ae65ea84c..b5a1493a4f7e8 100644 --- a/lib/Serialization/ASTReaderInternals.h +++ b/lib/Serialization/ASTReaderInternals.h @@ -40,7 +40,7 @@ class ModuleFile; namespace reader { -/// \brief Class that performs name lookup into a DeclContext stored +/// Class that performs name lookup into a DeclContext stored /// in an AST file. class ASTDeclContextNameLookupTrait { ASTReader &Reader; @@ -121,7 +121,7 @@ struct DeclContextLookupTable { MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table; }; -/// \brief Base class for the trait describing the on-disk hash table for the +/// Base class for the trait describing the on-disk hash table for the /// identifiers in an AST file. /// /// This class is not useful by itself; rather, it provides common @@ -156,7 +156,7 @@ public: static internal_key_type ReadKey(const unsigned char* d, unsigned n); }; -/// \brief Class that performs lookup for an identifier stored in an AST file. +/// Class that performs lookup for an identifier stored in an AST file. class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase { ASTReader &Reader; ModuleFile &F; @@ -182,12 +182,12 @@ public: ASTReader &getReader() const { return Reader; } }; -/// \brief The on-disk hash table used to contain information about +/// The on-disk hash table used to contain information about /// all of the identifiers in the program. using ASTIdentifierLookupTable = llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>; -/// \brief Class that performs lookup for a selector's entries in the global +/// Class that performs lookup for a selector's entries in the global /// method pool stored in an AST file. class ASTSelectorLookupTrait { ASTReader &Reader; @@ -229,11 +229,11 @@ public: data_type ReadData(Selector, const unsigned char* d, unsigned DataLen); }; -/// \brief The on-disk hash table used for the global method pool. +/// The on-disk hash table used for the global method pool. using ASTSelectorLookupTable = llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>; -/// \brief Trait class used to search the on-disk hash table containing all of +/// Trait class used to search the on-disk hash table containing all of /// the header search information. /// /// The on-disk hash table contains a mapping from each header path to @@ -280,7 +280,7 @@ public: data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen); }; -/// \brief The on-disk hash table used for known header files. +/// The on-disk hash table used for known header files. using HeaderFileInfoLookupTable = llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>; diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 6163b811c7691..d9d780b25b31e 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1,4 +1,4 @@ -//===--- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===// +//===- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------------------===// // // The LLVM Compiler Infrastructure // @@ -14,13 +14,55 @@ #include "clang/Serialization/ASTReader.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/AttrIterator.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclAccessPair.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OpenMPClause.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/CapturedStmt.h" +#include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Lex/Token.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <string> + using namespace clang; -using namespace clang::serialization; +using namespace serialization; namespace clang { @@ -68,19 +110,20 @@ namespace clang { ASTStmtReader(ASTRecordReader &Record, llvm::BitstreamCursor &Cursor) : Record(Record), DeclsCursor(Cursor) {} - /// \brief The number of record fields required for the Stmt class + /// The number of record fields required for the Stmt class /// itself. static const unsigned NumStmtFields = 0; - /// \brief The number of record fields required for the Expr class + /// The number of record fields required for the Expr class /// itself. static const unsigned NumExprFields = NumStmtFields + 7; - /// \brief Read and initialize a ExplicitTemplateArgumentList structure. + /// Read and initialize a ExplicitTemplateArgumentList structure. void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, TemplateArgumentLoc *ArgsLocArray, unsigned NumTemplateArgs); - /// \brief Read and initialize a ExplicitTemplateArgumentList structure. + + /// Read and initialize a ExplicitTemplateArgumentList structure. void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, unsigned NumTemplateArgs); @@ -89,7 +132,8 @@ namespace clang { void Visit##Type(Type *); #include "clang/AST/StmtNodes.inc" }; -} + +} // namespace clang void ASTStmtReader::ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, TemplateArgumentLoc *ArgsLocArray, @@ -146,7 +190,7 @@ void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) { void ASTStmtReader::VisitLabelStmt(LabelStmt *S) { VisitStmt(S); - LabelDecl *LD = ReadDeclAs<LabelDecl>(); + auto *LD = ReadDeclAs<LabelDecl>(); LD->setStmt(S); S->setDecl(LD); S->setSubStmt(Record.readSubStmt()); @@ -489,6 +533,12 @@ void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { E->setValue(Record.getContext(), Record.readAPInt()); } +void ASTStmtReader::VisitFixedPointLiteral(FixedPointLiteral *E) { + VisitExpr(E); + E->setLocation(ReadSourceLocation()); + E->setValue(Record.getContext(), Record.readAPInt()); +} + void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { VisitExpr(E); E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record.readInt())); @@ -508,8 +558,7 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { assert(Record.peekInt() == E->getNumConcatenated() && "Wrong number of concatenated tokens!"); Record.skipInts(1); - StringLiteral::StringKind kind = - static_cast<StringLiteral::StringKind>(Record.readInt()); + auto kind = static_cast<StringLiteral::StringKind>(Record.readInt()); bool isPascal = Record.readInt(); // Read string data @@ -553,6 +602,7 @@ void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) { E->setSubExpr(Record.readSubExpr()); E->setOpcode((UnaryOperator::Opcode)Record.readInt()); E->setOperatorLoc(ReadSourceLocation()); + E->setCanOverflow(Record.readInt()); } void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { @@ -565,7 +615,7 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { E->setRParenLoc(ReadSourceLocation()); E->setTypeSourceInfo(GetTypeSourceInfo()); for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - OffsetOfNode::Kind Kind = static_cast<OffsetOfNode::Kind>(Record.readInt()); + auto Kind = static_cast<OffsetOfNode::Kind>(Record.readInt()); SourceLocation Start = ReadSourceLocation(); SourceLocation End = ReadSourceLocation(); switch (Kind) { @@ -585,7 +635,7 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { break; case OffsetOfNode::Base: { - CXXBaseSpecifier *Base = new (Record.getContext()) CXXBaseSpecifier(); + auto *Base = new (Record.getContext()) CXXBaseSpecifier(); *Base = Record.readCXXBaseSpecifier(); E->setComponent(I, OffsetOfNode(Base)); break; @@ -675,7 +725,7 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { E->setCastKind((CastKind)Record.readInt()); CastExpr::path_iterator BaseI = E->path_begin(); while (NumBaseSpecs--) { - CXXBaseSpecifier *BaseSpec = new (Record.getContext()) CXXBaseSpecifier; + auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier; *BaseSpec = Record.readCXXBaseSpecifier(); *BaseI++ = BaseSpec; } @@ -719,6 +769,7 @@ ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); + E->setIsPartOfExplicitCast(Record.readInt()); } void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { @@ -749,7 +800,7 @@ void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { VisitExpr(E); - if (InitListExpr *SyntForm = cast_or_null<InitListExpr>(Record.readSubStmt())) + if (auto *SyntForm = cast_or_null<InitListExpr>(Record.readSubStmt())) E->setSyntacticForm(SyntForm); E->setLBraceLoc(ReadSourceLocation()); E->setRBraceLoc(ReadSourceLocation()); @@ -775,7 +826,7 @@ void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { } void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - typedef DesignatedInitExpr::Designator Designator; + using Designator = DesignatedInitExpr::Designator; VisitExpr(E); unsigned NumSubExprs = Record.readInt(); @@ -789,7 +840,7 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { while (Record.getIdx() < Record.size()) { switch ((DesignatorTypes)Record.readInt()) { case DESIG_FIELD_DECL: { - FieldDecl *Field = ReadDeclAs<FieldDecl>(); + auto *Field = ReadDeclAs<FieldDecl>(); SourceLocation DotLoc = ReadSourceLocation(); SourceLocation FieldLoc = ReadSourceLocation(); Designators.push_back(Designator(Field->getIdentifier(), DotLoc, @@ -994,9 +1045,9 @@ void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { assert(NumElements == E->getNumElements() && "Wrong number of elements"); bool HasPackExpansions = Record.readInt(); assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch"); - ObjCDictionaryLiteral::KeyValuePair *KeyValues = + auto *KeyValues = E->getTrailingObjects<ObjCDictionaryLiteral::KeyValuePair>(); - ObjCDictionaryLiteral::ExpansionData *Expansions = + auto *Expansions = E->getTrailingObjects<ObjCDictionaryLiteral::ExpansionData>(); for (unsigned I = 0; I != NumElements; ++I) { KeyValues[I].Key = Record.readSubExpr(); @@ -1047,8 +1098,8 @@ void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { unsigned MethodRefFlags = Record.readInt(); bool Implicit = Record.readInt() != 0; if (Implicit) { - ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>(); - ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>(); + auto *Getter = ReadDeclAs<ObjCMethodDecl>(); + auto *Setter = ReadDeclAs<ObjCMethodDecl>(); E->setImplicitProperty(Getter, Setter, MethodRefFlags); } else { E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(), MethodRefFlags); @@ -1085,8 +1136,7 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { E->SelLocsKind = Record.readInt(); E->setDelegateInitCall(Record.readInt()); E->IsImplicit = Record.readInt(); - ObjCMessageExpr::ReceiverKind Kind - = static_cast<ObjCMessageExpr::ReceiverKind>(Record.readInt()); + auto Kind = static_cast<ObjCMessageExpr::ReceiverKind>(Record.readInt()); switch (Kind) { case ObjCMessageExpr::Instance: E->setInstanceReceiver(Record.readSubExpr()); @@ -1520,8 +1570,8 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { unsigned NumDecls = Record.readInt(); UnresolvedSet<8> Decls; for (unsigned i = 0; i != NumDecls; ++i) { - NamedDecl *D = ReadDeclAs<NamedDecl>(); - AccessSpecifier AS = (AccessSpecifier)Record.readInt(); + auto *D = ReadDeclAs<NamedDecl>(); + auto AS = (AccessSpecifier)Record.readInt(); Decls.addDecl(D, AS); } E->initializeResults(Record.getContext(), Decls.begin(), Decls.end()); @@ -1555,7 +1605,7 @@ void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { E->Loc = Range.getBegin(); E->RParenLoc = Range.getEnd(); - TypeSourceInfo **Args = E->getTrailingObjects<TypeSourceInfo *>(); + auto **Args = E->getTrailingObjects<TypeSourceInfo *>(); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) Args[I] = GetTypeSourceInfo(); } @@ -1639,7 +1689,7 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { E->NumParameters = Record.readInt(); E->ParamPack = ReadDeclAs<ParmVarDecl>(); E->NameLoc = ReadSourceLocation(); - ParmVarDecl **Parms = E->getTrailingObjects<ParmVarDecl *>(); + auto **Parms = E->getTrailingObjects<ParmVarDecl *>(); for (unsigned i = 0, n = E->NumParameters; i != n; ++i) Parms[i] = ReadDeclAs<ParmVarDecl>(); } @@ -1647,7 +1697,7 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); E->State = Record.readSubExpr(); - auto VD = ReadDeclAs<ValueDecl>(); + auto *VD = ReadDeclAs<ValueDecl>(); unsigned ManglingNumber = Record.readInt(); E->setExtendingDecl(VD, ManglingNumber); } @@ -1666,6 +1716,7 @@ void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); E->SourceExpr = Record.readSubExpr(); E->Loc = ReadSourceLocation(); + E->setIsUnique(Record.readInt()); } void ASTStmtReader::VisitTypoExpr(TypoExpr *E) { @@ -1756,19 +1807,23 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { //===----------------------------------------------------------------------===// namespace clang { + class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> { ASTStmtReader *Reader; ASTContext &Context; + public: OMPClauseReader(ASTStmtReader *R, ASTRecordReader &Record) : Reader(R), Context(Record.getContext()) {} + #define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" OMPClause *readClause(); void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C); void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C); }; -} + +} // namespace clang OMPClause *OMPClauseReader::readClause() { OMPClause *C; @@ -2393,7 +2448,7 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) { Components.reserve(TotalComponents); for (unsigned i = 0; i < TotalComponents; ++i) { Expr *AssociatedExpr = Reader->Record.readSubExpr(); - ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); + auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); Components.push_back(OMPClauseMappableExprCommon::MappableComponent( AssociatedExpr, AssociatedDecl)); } @@ -2487,7 +2542,7 @@ void OMPClauseReader::VisitOMPToClause(OMPToClause *C) { Components.reserve(TotalComponents); for (unsigned i = 0; i < TotalComponents; ++i) { Expr *AssociatedExpr = Reader->Record.readSubExpr(); - ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); + auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); Components.push_back(OMPClauseMappableExprCommon::MappableComponent( AssociatedExpr, AssociatedDecl)); } @@ -2529,7 +2584,7 @@ void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) { Components.reserve(TotalComponents); for (unsigned i = 0; i < TotalComponents; ++i) { Expr *AssociatedExpr = Reader->Record.readSubExpr(); - ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); + auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); Components.push_back(OMPClauseMappableExprCommon::MappableComponent( AssociatedExpr, AssociatedDecl)); } @@ -2579,7 +2634,7 @@ void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) { Components.reserve(TotalComponents); for (unsigned i = 0; i < TotalComponents; ++i) { Expr *AssociatedExpr = Reader->Record.readSubExpr(); - ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); + auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); Components.push_back(OMPClauseMappableExprCommon::MappableComponent( AssociatedExpr, AssociatedDecl)); } @@ -2622,7 +2677,7 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { Components.reserve(TotalComponents); for (unsigned i = 0; i < TotalComponents; ++i) { Expr *AssociatedExpr = Reader->Record.readSubExpr(); - ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); + auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>(); Components.push_back(OMPClauseMappableExprCommon::MappableComponent( AssociatedExpr, AssociatedDecl)); } @@ -2632,6 +2687,7 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { //===----------------------------------------------------------------------===// // OpenMP Directives. //===----------------------------------------------------------------------===// + void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { E->setLocStart(ReadSourceLocation()); E->setLocEnd(ReadSourceLocation()); @@ -2917,6 +2973,7 @@ void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) { Record.skipInts(1); VisitOMPExecutableDirective(D); } + void ASTStmtReader::VisitOMPDistributeParallelForDirective( OMPDistributeParallelForDirective *D) { VisitOMPLoopDirective(D); @@ -3025,7 +3082,6 @@ Expr *ASTReader::ReadSubExpr() { // stack. Evaluation terminates when we see a STMT_STOP record, and // the single remaining expression on the stack is our result. Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { - ReadingKindTracker ReadingKind(Read_Stmt, *this); llvm::BitstreamCursor &Cursor = F.DeclsCursor; @@ -3254,15 +3310,15 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { bool HadMultipleCandidates = Record.readInt(); - NamedDecl *FoundD = Record.readDeclAs<NamedDecl>(); - AccessSpecifier AS = (AccessSpecifier)Record.readInt(); + auto *FoundD = Record.readDeclAs<NamedDecl>(); + auto AS = (AccessSpecifier)Record.readInt(); DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); QualType T = Record.readType(); - ExprValueKind VK = static_cast<ExprValueKind>(Record.readInt()); - ExprObjectKind OK = static_cast<ExprObjectKind>(Record.readInt()); + auto VK = static_cast<ExprValueKind>(Record.readInt()); + auto OK = static_cast<ExprObjectKind>(Record.readInt()); Expr *Base = ReadSubExpr(); - ValueDecl *MemberD = Record.readDeclAs<ValueDecl>(); + auto *MemberD = Record.readDeclAs<ValueDecl>(); SourceLocation MemberLoc = Record.readSourceLocation(); DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); bool IsArrow = Record.readInt(); @@ -3382,93 +3438,121 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_OBJC_STRING_LITERAL: S = new (Context) ObjCStringLiteral(Empty); break; + case EXPR_OBJC_BOXED_EXPRESSION: S = new (Context) ObjCBoxedExpr(Empty); break; + case EXPR_OBJC_ARRAY_LITERAL: S = ObjCArrayLiteral::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields]); break; + case EXPR_OBJC_DICTIONARY_LITERAL: S = ObjCDictionaryLiteral::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields], Record[ASTStmtReader::NumExprFields + 1]); break; + case EXPR_OBJC_ENCODE: S = new (Context) ObjCEncodeExpr(Empty); break; + case EXPR_OBJC_SELECTOR_EXPR: S = new (Context) ObjCSelectorExpr(Empty); break; + case EXPR_OBJC_PROTOCOL_EXPR: S = new (Context) ObjCProtocolExpr(Empty); break; + case EXPR_OBJC_IVAR_REF_EXPR: S = new (Context) ObjCIvarRefExpr(Empty); break; + case EXPR_OBJC_PROPERTY_REF_EXPR: S = new (Context) ObjCPropertyRefExpr(Empty); break; + case EXPR_OBJC_SUBSCRIPT_REF_EXPR: S = new (Context) ObjCSubscriptRefExpr(Empty); break; + case EXPR_OBJC_KVC_REF_EXPR: llvm_unreachable("mismatching AST file"); + case EXPR_OBJC_MESSAGE_EXPR: S = ObjCMessageExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields], Record[ASTStmtReader::NumExprFields + 1]); break; + case EXPR_OBJC_ISA: S = new (Context) ObjCIsaExpr(Empty); break; + case EXPR_OBJC_INDIRECT_COPY_RESTORE: S = new (Context) ObjCIndirectCopyRestoreExpr(Empty); break; + case EXPR_OBJC_BRIDGED_CAST: S = new (Context) ObjCBridgedCastExpr(Empty); break; + case STMT_OBJC_FOR_COLLECTION: S = new (Context) ObjCForCollectionStmt(Empty); break; + case STMT_OBJC_CATCH: S = new (Context) ObjCAtCatchStmt(Empty); break; + case STMT_OBJC_FINALLY: S = new (Context) ObjCAtFinallyStmt(Empty); break; + case STMT_OBJC_AT_TRY: S = ObjCAtTryStmt::CreateEmpty(Context, Record[ASTStmtReader::NumStmtFields], Record[ASTStmtReader::NumStmtFields + 1]); break; + case STMT_OBJC_AT_SYNCHRONIZED: S = new (Context) ObjCAtSynchronizedStmt(Empty); break; + case STMT_OBJC_AT_THROW: S = new (Context) ObjCAtThrowStmt(Empty); break; + case STMT_OBJC_AUTORELEASE_POOL: S = new (Context) ObjCAutoreleasePoolStmt(Empty); break; + case EXPR_OBJC_BOOL_LITERAL: S = new (Context) ObjCBoolLiteralExpr(Empty); break; + case EXPR_OBJC_AVAILABILITY_CHECK: S = new (Context) ObjCAvailabilityCheckExpr(Empty); break; + case STMT_SEH_LEAVE: S = new (Context) SEHLeaveStmt(Empty); break; + case STMT_SEH_EXCEPT: S = new (Context) SEHExceptStmt(Empty); break; + case STMT_SEH_FINALLY: S = new (Context) SEHFinallyStmt(Empty); break; + case STMT_SEH_TRY: S = new (Context) SEHTryStmt(Empty); break; + case STMT_CXX_CATCH: S = new (Context) CXXCatchStmt(Empty); break; @@ -3750,11 +3834,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } - case STMT_OMP_TARGET_TEAMS_DIRECTIVE: { + case STMT_OMP_TARGET_TEAMS_DIRECTIVE: S = OMPTargetTeamsDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); break; - } case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE: { auto NumClauses = Record[ASTStmtReader::NumStmtFields]; @@ -3847,36 +3930,47 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_CXX_NULL_PTR_LITERAL: S = new (Context) CXXNullPtrLiteralExpr(Empty); break; + case EXPR_CXX_TYPEID_EXPR: S = new (Context) CXXTypeidExpr(Empty, true); break; + case EXPR_CXX_TYPEID_TYPE: S = new (Context) CXXTypeidExpr(Empty, false); break; + case EXPR_CXX_UUIDOF_EXPR: S = new (Context) CXXUuidofExpr(Empty, true); break; + case EXPR_CXX_PROPERTY_REF_EXPR: S = new (Context) MSPropertyRefExpr(Empty); break; + case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR: S = new (Context) MSPropertySubscriptExpr(Empty); break; + case EXPR_CXX_UUIDOF_TYPE: S = new (Context) CXXUuidofExpr(Empty, false); break; + case EXPR_CXX_THIS: S = new (Context) CXXThisExpr(Empty); break; + case EXPR_CXX_THROW: S = new (Context) CXXThrowExpr(Empty); break; + case EXPR_CXX_DEFAULT_ARG: S = new (Context) CXXDefaultArgExpr(Empty); break; + case EXPR_CXX_DEFAULT_INIT: S = new (Context) CXXDefaultInitExpr(Empty); break; + case EXPR_CXX_BIND_TEMPORARY: S = new (Context) CXXBindTemporaryExpr(Empty); break; @@ -3884,12 +3978,15 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_CXX_SCALAR_VALUE_INIT: S = new (Context) CXXScalarValueInitExpr(Empty); break; + case EXPR_CXX_NEW: S = new (Context) CXXNewExpr(Empty); break; + case EXPR_CXX_DELETE: S = new (Context) CXXDeleteExpr(Empty); break; + case EXPR_CXX_PSEUDO_DESTRUCTOR: S = new (Context) CXXPseudoDestructorExpr(Empty); break; @@ -4033,7 +4130,6 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_DEPENDENT_COAWAIT: S = new (Context) DependentCoawaitExpr(Empty); break; - } // We hit a STMT_STOP, so we're done with this expression. diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 1e72ced2ee364..1a8d806e9d246 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -53,7 +53,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" @@ -79,16 +78,17 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compression.h" +#include "llvm/Support/DJB.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/Error.h" @@ -97,6 +97,7 @@ #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -138,10 +139,10 @@ namespace clang { ASTWriter &Writer; ASTRecordWriter Record; - /// \brief Type code that corresponds to the record generated. + /// Type code that corresponds to the record generated. TypeCode Code = static_cast<TypeCode>(0); - /// \brief Abbreviation to use for the record, if any. + /// Abbreviation to use for the record, if any. unsigned AbbrevToUse = 0; public: @@ -276,6 +277,7 @@ void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { Record.push_back(C.getCC()); Record.push_back(C.getProducesResult()); Record.push_back(C.getNoCallerSavedRegs()); + Record.push_back(C.getNoCfCheck()); if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult()) AbbrevToUse = 0; @@ -293,7 +295,7 @@ static void addExceptionSpec(const FunctionProtoType *T, Record.push_back(T->getNumExceptions()); for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) Record.AddTypeRef(T->getExceptionType(I)); - } else if (T->getExceptionSpecType() == EST_ComputedNoexcept) { + } else if (isComputedNoexcept(T->getExceptionSpecType())) { Record.AddStmt(T->getNoexceptExpr()); } else if (T->getExceptionSpecType() == EST_Uninstantiated) { Record.AddDeclRef(T->getExceptionSpecDecl()); @@ -453,7 +455,15 @@ ASTTypeWriter::VisitDependentSizedExtVectorType( Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } -void +void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { + Record.AddTypeRef(T->getElementType()); + Record.AddStmt(const_cast<Expr*>(T->getSizeExpr())); + Record.AddSourceLocation(T->getAttributeLoc()); + Record.push_back(T->getVectorKind()); + Code = TYPE_DEPENDENT_SIZED_VECTOR; +} + +void ASTTypeWriter::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { Record.AddTypeRef(T->getPointeeType()); @@ -511,6 +521,7 @@ void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { Record.push_back(T->getKeyword()); Record.AddNestedNameSpecifier(T->getQualifier()); Record.AddTypeRef(T->getNamedType()); + Record.AddDeclRef(T->getOwnedTagDecl()); Code = TYPE_ELABORATED; } @@ -661,7 +672,7 @@ void TypeLocWriter::VisitDependentAddressSpaceTypeLoc( SourceRange range = TL.getAttrOperandParensRange(); Record.AddSourceLocation(range.getBegin()); Record.AddSourceLocation(range.getEnd()); - Record.AddStmt(TL.getAttrExprOperand()); + Record.AddStmt(TL.getAttrExprOperand()); } void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( @@ -673,6 +684,11 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitDependentVectorTypeLoc( + DependentVectorTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } @@ -884,6 +900,7 @@ void ASTWriter::WriteTypeAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult Abv->Add(BitCodeAbbrevOp(0)); // NoCallerSavedRegs + Abv->Add(BitCodeAbbrevOp(0)); // NoCfCheck // FunctionProtoType Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn @@ -1104,6 +1121,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(UNUSED_FILESCOPED_DECLS); RECORD(PPD_ENTITIES_OFFSETS); RECORD(VTABLE_USES); + RECORD(PPD_SKIPPED_RANGES); RECORD(REFERENCED_SELECTOR_POOL); RECORD(TU_UPDATE_LEXICAL); RECORD(SEMA_DECL_REFS); @@ -1293,7 +1311,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_PRAGMA_COMMENT); RECORD(DECL_PRAGMA_DETECT_MISMATCH); RECORD(DECL_OMP_DECLARE_REDUCTION); - + // Statements and Exprs can occur in the Decls and Types block. AddStmtsExprs(Stream, Record); @@ -1316,7 +1334,7 @@ void ASTWriter::WriteBlockInfoBlock() { Stream.ExitBlock(); } -/// \brief Prepares a path for being written to an AST file by converting it +/// Prepares a path for being written to an AST file by converting it /// to an absolute path and removing nested './'s. /// /// \return \c true if the path was changed. @@ -1326,7 +1344,7 @@ static bool cleanPathForOutput(FileManager &FileMgr, return Changed | llvm::sys::path::remove_dots(Path); } -/// \brief Adjusts the given filename to only write out the portion of the +/// Adjusts the given filename to only write out the portion of the /// filename that is not part of the system root directory. /// /// \param Filename the file name to adjust. @@ -1436,7 +1454,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, return Signature; } -/// \brief Write the control block. +/// Write the control block. void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, const std::string &OutputFile) { @@ -1444,7 +1462,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); RecordData Record; - + // Metadata auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>(); MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA)); @@ -1454,16 +1472,23 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min. MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PCHHasObjectFile MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev)); assert((!WritingModule || isysroot.empty()) && "writing module as a relocatable PCH?"); { - RecordData::value_type Record[] = {METADATA, VERSION_MAJOR, VERSION_MINOR, - CLANG_VERSION_MAJOR, CLANG_VERSION_MINOR, - !isysroot.empty(), IncludeTimestamps, - ASTHasCompilerErrors}; + RecordData::value_type Record[] = { + METADATA, + VERSION_MAJOR, + VERSION_MINOR, + CLANG_VERSION_MAJOR, + CLANG_VERSION_MINOR, + !isysroot.empty(), + IncludeTimestamps, + Context.getLangOpts().BuildingPCHWithObjectFile, + ASTHasCompilerErrors}; Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); } @@ -1732,7 +1757,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, namespace { -/// \brief An input file. +/// An input file. struct InputFileEntry { const FileEntry *File; bool IsSystemFile; @@ -1842,7 +1867,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, // Source Manager Serialization //===----------------------------------------------------------------------===// -/// \brief Create an abbreviation for the SLocEntry that refers to a +/// Create an abbreviation for the SLocEntry that refers to a /// file. static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { using namespace llvm; @@ -1861,7 +1886,7 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { return Stream.EmitAbbrev(std::move(Abbrev)); } -/// \brief Create an abbreviation for the SLocEntry that refers to a +/// Create an abbreviation for the SLocEntry that refers to a /// buffer. static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { using namespace llvm; @@ -1876,7 +1901,7 @@ static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { return Stream.EmitAbbrev(std::move(Abbrev)); } -/// \brief Create an abbreviation for the SLocEntry that refers to a +/// Create an abbreviation for the SLocEntry that refers to a /// buffer's blob. static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream, bool Compressed) { @@ -1891,7 +1916,7 @@ static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream, return Stream.EmitAbbrev(std::move(Abbrev)); } -/// \brief Create an abbreviation for the SLocEntry that refers to a macro +/// Create an abbreviation for the SLocEntry that refers to a macro /// expansion. static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) { using namespace llvm; @@ -1902,6 +1927,7 @@ static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length return Stream.EmitAbbrev(std::move(Abbrev)); } @@ -1911,11 +1937,11 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; - + // Keep track of the framework names we've used during serialization. SmallVector<char, 128> FrameworkStringData; llvm::StringMap<unsigned> FrameworkNameOffset; - + public: HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} @@ -1928,7 +1954,7 @@ namespace { using UnresolvedModule = llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>; - + struct data_type { const HeaderFileInfo &HFI; ArrayRef<ModuleMap::KnownHeader> KnownHeaders; @@ -1938,19 +1964,19 @@ namespace { using hash_value_type = unsigned; using offset_type = unsigned; - + 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. return llvm::hash_combine(key.Size, key.ModTime); } - + 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); + endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write<uint16_t>(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; @@ -1966,7 +1992,7 @@ namespace { void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); LE.write<uint64_t>(key.Size); KeyLen -= 8; LE.write<uint64_t>(key.ModTime); @@ -1978,16 +2004,16 @@ namespace { data_type_ref Data, unsigned DataLen) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; - + unsigned char Flags = (Data.HFI.isImport << 5) | (Data.HFI.isPragmaOnce << 4) | (Data.HFI.DirInfo << 1) | Data.HFI.IndexHeaderMapHeader; LE.write<uint8_t>(Flags); LE.write<uint16_t>(Data.HFI.NumIncludes); - + if (!Data.HFI.ControllingMacro) LE.write<uint32_t>(Data.HFI.ControllingMacroID); else @@ -2000,10 +2026,10 @@ namespace { = FrameworkNameOffset.find(Data.HFI.Framework); if (Pos == FrameworkNameOffset.end()) { Offset = FrameworkStringData.size() + 1; - FrameworkStringData.append(Data.HFI.Framework.begin(), + FrameworkStringData.append(Data.HFI.Framework.begin(), Data.HFI.Framework.end()); FrameworkStringData.push_back(0); - + FrameworkNameOffset[Data.HFI.Framework] = Offset; } else Offset = Pos->second; @@ -2027,14 +2053,14 @@ namespace { assert(Out.tell() - Start == DataLen && "Wrong data length"); } - + const char *strings_begin() const { return FrameworkStringData.begin(); } const char *strings_end() const { return FrameworkStringData.end(); } }; } // namespace -/// \brief Write the header search block for the list of files that +/// Write the header search block for the list of files that /// /// \param HS The header search structure to save. void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { @@ -2100,7 +2126,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); - + if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); @@ -2148,7 +2174,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { llvm::raw_svector_ostream Out(TableData); // Make sure that no bucket is at offset 0 - endian::Writer<little>(Out).write<uint32_t>(0); + endian::write<uint32_t>(Out, 0, little); BucketOffset = Generator.Emit(Out, GeneratorTrait); } @@ -2162,13 +2188,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - + // Write the header search table RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset, NumHeaderSearchEntries, TableData.size()}; TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData); - + // Free all of the strings we had to duplicate. for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) free(const_cast<char *>(SavedStrings[I])); @@ -2198,7 +2224,7 @@ static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob, Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob); } -/// \brief Writes the block containing the serialized form of the +/// Writes the block containing the serialized form of the /// source manager. /// /// TODO: We should probably use an on-disk hash table (stored in a @@ -2268,7 +2294,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(InputFileIDs[Content->OrigEntry]); Record.push_back(File.NumCreatedFIDs); - + FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); if (FDI != FileDeclIDs.end()) { Record.push_back(FDI->second->FirstDeclIndex); @@ -2277,9 +2303,9 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(0); Record.push_back(0); } - + Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record); - + if (Content->BufferOverridden || Content->IsTransient) EmitBlob = true; } else { @@ -2318,6 +2344,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, ? SourceLocation() : Expansion.getExpansionLocEnd(), Record); + Record.push_back(Expansion.isExpansionTokenRange()); // Compute the token length for this macro expansion. unsigned NextOffset = SourceMgr.getNextLocalOffset(); @@ -2420,7 +2447,7 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, return false; } -/// \brief Writes the block containing the serialized form of the +/// Writes the block containing the serialized form of the /// preprocessor. void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); @@ -2480,8 +2507,8 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { MacroIdentifiers.push_back(Id.second); // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. - std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(), - llvm::less_ptr<IdentifierInfo>()); + llvm::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(), + llvm::less_ptr<IdentifierInfo>()); // Emit the macro directives as a list and associate the offset with the // identifier they belong to. @@ -2540,7 +2567,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { Record.clear(); } - /// \brief Offsets of each of the macros into the bitstream, indexed by + /// Offsets of each of the macros into the bitstream, indexed by /// the local macro ID /// /// For each identifier that is associated with a macro, this map @@ -2640,8 +2667,8 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { // If the preprocessor has a preprocessing record, emit it. unsigned NumPreprocessingRecords = 0; using namespace llvm; - - // Set up the abbreviation for + + // Set up the abbreviation for unsigned InclusionAbbrev = 0; { auto Abbrev = std::make_shared<BitCodeAbbrev>(); @@ -2653,15 +2680,15 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); } - - unsigned FirstPreprocessorEntityID - = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0) + + unsigned FirstPreprocessorEntityID + = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0) + NUM_PREDEF_PP_ENTITY_IDS; unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID; RecordData Record; for (PreprocessingRecord::iterator E = PPRec.local_begin(), EEnd = PPRec.local_end(); - E != EEnd; + E != EEnd; (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { Record.clear(); @@ -2702,7 +2729,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); continue; } - + llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); } Stream.ExitBlock(); @@ -2726,6 +2753,26 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record, bytes(PreprocessedEntityOffsets)); } + + // Write the skipped region table for the preprocessing record. + ArrayRef<SourceRange> SkippedRanges = PPRec.getSkippedRanges(); + if (SkippedRanges.size() > 0) { + std::vector<PPSkippedRange> SerializedSkippedRanges; + SerializedSkippedRanges.reserve(SkippedRanges.size()); + for (auto const& Range : SkippedRanges) + SerializedSkippedRanges.emplace_back(Range); + + using namespace llvm; + auto Abbrev = std::make_shared<BitCodeAbbrev>(); + Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); + + Record.clear(); + Record.push_back(PPD_SKIPPED_RANGES); + Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record, + bytes(SerializedSkippedRanges)); + } } unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) { @@ -2755,21 +2802,21 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) { return ID; } -/// \brief Compute the number of modules within the given tree (including the +/// Compute the number of modules within the given tree (including the /// given module). static unsigned getNumberOfModules(Module *Mod) { unsigned ChildModules = 0; for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) ChildModules += getNumberOfModules(*Sub); - + return ChildModules + 1; } void ASTWriter::WriteSubmodules(Module *WritingModule) { // Enter the submodule description block. Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5); - + // Write the abbreviations needed for the submodules block. using namespace llvm; @@ -2786,6 +2833,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh... + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); @@ -2862,7 +2910,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { getNumberOfModules(WritingModule), FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS}; Stream.EmitRecord(SUBMODULE_METADATA, Record); - + // Write all of the submodules. std::queue<Module *> Q; Q.push(WritingModule); @@ -2890,7 +2938,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Mod->InferSubmodules, Mod->InferExplicitSubmodules, Mod->InferExportWildcard, - Mod->ConfigMacrosExhaustive}; + Mod->ConfigMacrosExhaustive, + Mod->ModuleMapIsPrivate}; Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); } @@ -2938,7 +2987,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName()); } - // Emit the imports. + // Emit the imports. if (!Mod->Imports.empty()) { RecordData Record; for (auto *I : Mod->Imports) @@ -2946,7 +2995,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecord(SUBMODULE_IMPORTS, Record); } - // Emit the exports. + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; for (const auto &E : Mod->Exports) { @@ -2996,12 +3045,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS}; Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule); } - + // Queue up the submodules of this module. for (auto *M : Mod->submodules()) Q.push(M); } - + Stream.ExitBlock(); assert((NextSubmoduleID - FirstSubmoduleID == @@ -3040,7 +3089,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, unsigned &DiagStateID = DiagStateIDMap[State]; Record.push_back(DiagStateID); - + if (DiagStateID == 0) { DiagStateID = ++CurrID; @@ -3071,8 +3120,11 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, !FileIDAndFile.second.HasLocalTransitions) continue; ++NumLocations; - AddSourceLocation(Diag.SourceMgr->getLocForStartOfFile(FileIDAndFile.first), - Record); + + SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0); + assert(!Loc.isInvalid() && "start loc for valid FileID is invalid"); + AddSourceLocation(Loc, Record); + Record.push_back(FileIDAndFile.second.StateTransitions.size()); for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { Record.push_back(StatePoint.Offset); @@ -3099,7 +3151,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, // Type Serialization //===----------------------------------------------------------------------===// -/// \brief Write the representation of a type to the AST stream. +/// Write the representation of a type to the AST stream. void ASTWriter::WriteType(QualType T) { TypeIdx &IdxRef = TypeIdxs[T]; if (IdxRef.getIndex() == 0) // we haven't seen this type before. @@ -3131,11 +3183,11 @@ void ASTWriter::WriteType(QualType T) { // Declaration Serialization //===----------------------------------------------------------------------===// -/// \brief Write the block containing all of the declaration IDs +/// Write the block containing all of the declaration IDs /// lexically declared within the given DeclContext. /// /// \returns the offset of the DECL_CONTEXT_LEXICAL block within the -/// bistream, or 0 if no block was written. +/// bitstream, or 0 if no block was written. uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC) { if (DC->decls_empty()) @@ -3190,8 +3242,8 @@ void ASTWriter::WriteFileDeclIDsMap() { SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs( FileDeclIDs.begin(), FileDeclIDs.end()); - std::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(), - llvm::less_first()); + llvm::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(), + llvm::less_first()); // Join the vectors of DeclIDs from all files. SmallVector<DeclID, 256> FileGroupedDeclIDs; @@ -3214,6 +3266,9 @@ void ASTWriter::WriteFileDeclIDsMap() { void ASTWriter::WriteComments() { Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3); + auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); }); + if (!PP->getPreprocessorOpts().WriteCommentListToPCH) + return; ArrayRef<RawComment *> RawComments = Context->Comments.getComments(); RecordData Record; for (const auto *I : RawComments) { @@ -3224,7 +3279,6 @@ void ASTWriter::WriteComments() { Record.push_back(I->isAlmostTrailingComment()); Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record); } - Stream.ExitBlock(); } //===----------------------------------------------------------------------===// @@ -3261,7 +3315,7 @@ public: data_type_ref Methods) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); LE.write<uint16_t>(KeyLen); unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts @@ -3280,7 +3334,7 @@ public: void EmitKey(raw_ostream& Out, Selector Sel, unsigned) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); uint64_t Start = Out.tell(); assert((Start >> 32) == 0 && "Selector key offset too large"); Writer.SetSelectorOffset(Sel, Start); @@ -3297,7 +3351,7 @@ public: data_type_ref Methods, unsigned DataLen) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; LE.write<uint32_t>(Methods.ID); unsigned NumInstanceMethods = 0; @@ -3343,7 +3397,7 @@ public: } // namespace -/// \brief Write ObjC data: selectors and the method pool. +/// Write ObjC data: selectors and the method pool. /// /// The method pool contains both instance and factory methods, stored /// in an on-disk hash table indexed by the selector. The hash table also @@ -3409,7 +3463,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { ASTMethodPoolTrait Trait(*this); llvm::raw_svector_ostream Out(MethodPool); // Make sure that no bucket is at offset 0 - endian::Writer<little>(Out).write<uint32_t>(0); + endian::write<uint32_t>(Out, 0, little); BucketOffset = Generator.Emit(Out, Trait); } @@ -3447,7 +3501,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { } } -/// \brief Write the selectors referenced in @selector expression into AST file. +/// Write the selectors referenced in @selector expression into AST file. void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { using namespace llvm; @@ -3522,8 +3576,8 @@ class ASTIdentifierTableTrait { bool IsModule; bool NeedDecls; ASTWriter::RecordData *InterestingIdentifierOffsets; - - /// \brief Determines whether this is an "interesting" identifier that needs a + + /// Determines whether this is an "interesting" identifier that needs a /// full IdentifierInfo structure written into the hash table. Notably, this /// doesn't check whether the name has macros defined; use PublicMacroIterator /// to check that. @@ -3558,7 +3612,7 @@ public: bool needDecls() const { return NeedDecls; } static hash_value_type ComputeHash(const IdentifierInfo* II) { - return llvm::HashString(II->getName()); + return llvm::djbHash(II->getName()); } bool isInterestingIdentifier(const IdentifierInfo *II) { @@ -3591,7 +3645,7 @@ public: using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen); LE.write<uint16_t>(DataLen); @@ -3620,7 +3674,7 @@ public: IdentID ID, unsigned) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); auto MacroOffset = Writer.getMacroDirectivesOffset(II); if (!isInterestingIdentifier(II, MacroOffset)) { @@ -3665,12 +3719,12 @@ public: } // namespace -/// \brief Write the identifier table into the AST file. +/// Write the identifier table into the AST file. /// /// The identifier table consists of a blob containing string data /// (the actual identifiers themselves) and a separate "offsets" index /// that maps identifier IDs to locations within the blob. -void ASTWriter::WriteIdentifierTable(Preprocessor &PP, +void ASTWriter::WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule) { using namespace llvm; @@ -3695,7 +3749,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, IIs.push_back(ID.second); // Sort the identifiers lexicographically before getting them references so // that their order is stable. - std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>()); + llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>()); for (const IdentifierInfo *II : IIs) if (Trait.isInterestingNonMacroIdentifier(II)) getIdentifierRef(II); @@ -3724,7 +3778,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 - endian::Writer<little>(Out).write<uint32_t>(0); + endian::write<uint32_t>(Out, 0, little); BucketOffset = Generator.Emit(Out, Trait); } @@ -3820,8 +3874,7 @@ public: using namespace llvm::support; - endian::Writer<little>(Out) - .write<uint32_t>(Writer.getChain()->getModuleFileID(F)); + endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F), little); } std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out, @@ -3829,7 +3882,7 @@ public: data_type_ref Lookup) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); unsigned KeyLen = 1; switch (Name.getKind()) { case DeclarationName::Identifier: @@ -3863,7 +3916,7 @@ public: void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); LE.write<uint8_t>(Name.getKind()); switch (Name.getKind()) { case DeclarationName::Identifier: @@ -3895,7 +3948,7 @@ public: unsigned DataLen) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) LE.write<uint32_t>(DeclIDs[I]); @@ -3993,7 +4046,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, } // Sort the names into a stable order. - std::sort(Names.begin(), Names.end()); + llvm::sort(Names.begin(), Names.end()); if (auto *D = dyn_cast<CXXRecordDecl>(DC)) { // We need to establish an ordering of constructor and conversion function @@ -4096,7 +4149,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr); } -/// \brief Write the block containing all of the declaration IDs +/// Write the block containing all of the declaration IDs /// visible from the given DeclContext. /// /// \returns the offset of the DECL_CONTEXT_VISIBLE block within the @@ -4130,7 +4183,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, std::make_pair(Entry.first, Entry.second.getLookupResult())); } - std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first()); + llvm::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first()); for (auto &NameAndResult : LookupResults) { DeclarationName Name = NameAndResult.first; DeclContext::lookup_result Result = NameAndResult.second; @@ -4186,7 +4239,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, return Offset; } -/// \brief Write an UPDATE_VISIBLE block for the given context. +/// Write an UPDATE_VISIBLE block for the given context. /// /// UPDATE_VISIBLE blocks contain the declarations that are added to an existing /// DeclContext in a dependent AST file. As such, they only exist for the TU @@ -4211,13 +4264,13 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); } -/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions. +/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions. void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) { RecordData::value_type Record[] = {Opts.getInt()}; Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record); } -/// \brief Write an OPENCL_EXTENSIONS block for the given OpenCLOptions. +/// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions. void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { if (!SemaRef.Context.getLangOpts().OpenCL) return; @@ -4274,16 +4327,16 @@ void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) { void ASTWriter::WriteObjCCategories() { SmallVector<ObjCCategoriesInfo, 2> CategoriesMap; RecordData Categories; - + for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) { unsigned Size = 0; unsigned StartIndex = Categories.size(); - + ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I]; - + // Allocate space for the size. Categories.push_back(0); - + // Add the categories. for (ObjCInterfaceDecl::known_categories_iterator Cat = Class->known_categories_begin(), @@ -4292,10 +4345,10 @@ void ASTWriter::WriteObjCCategories() { assert(getDeclID(*Cat) != 0 && "Bogus category"); AddDeclRef(*Cat, Categories); } - + // Update the size. Categories[StartIndex] = Size; - + // Record this interface -> category map. ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex }; CategoriesMap.push_back(CatInfo); @@ -4344,7 +4397,7 @@ 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. +/// Write the state of 'pragma clang optimize' at the end of the module. void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) { RecordData Record; SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation(); @@ -4352,14 +4405,14 @@ void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) { Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record); } -/// \brief Write the state of 'pragma ms_struct' at the end of the module. +/// Write the state of 'pragma ms_struct' at the end of the module. void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) { RecordData Record; Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF); Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record); } -/// \brief Write the state of 'pragma pointers_to_members' at the end of the +/// Write the state of 'pragma pointers_to_members' at the end of the //module. void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) { RecordData Record; @@ -4368,7 +4421,7 @@ void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) { Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record); } -/// \brief Write the state of 'pragma pack' at the end of the module. +/// Write the state of 'pragma pack' at the end of the module. void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) { // Don't serialize pragma pack state for modules, since it should only take // effect on a per-submodule basis. @@ -4427,7 +4480,7 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef, // General Serialization Routines //===----------------------------------------------------------------------===// -/// \brief Emit the list of attributes to the specified record. +/// Emit the list of attributes to the specified record. void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) { auto &Record = *this; Record.push_back(Attrs.size()); @@ -4501,7 +4554,7 @@ void ASTWriter::AddVersionTuple(const VersionTuple &Version, Record.push_back(0); } -/// \brief Note that the identifier II occurs at the given offset +/// Note that the identifier II occurs at the given offset /// within the identifier table. void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { IdentID ID = IdentifierIDs[II]; @@ -4511,7 +4564,7 @@ void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { IdentifierOffsets[ID - FirstIdentID] = Offset; } -/// \brief Note that the selector Sel occurs at the given offset +/// Note that the selector Sel occurs at the given offset /// within the method pool/selector table. void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { unsigned ID = SelectorIDs[Sel]; @@ -4555,7 +4608,7 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, WritingAST = true; ASTHasCompilerErrors = hasErrors; - + // Emit the file header. Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'P', 8); @@ -4603,7 +4656,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // Make sure that the AST reader knows to finalize itself. if (Chain) Chain->finalizeForWriting(); - + ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; @@ -4644,7 +4697,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // headers. RecordData TentativeDefinitions; AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); - + // Build a record containing all of the file scoped decls in this file. RecordData UnusedFileScopedDecls; if (!isModule) @@ -4732,13 +4785,15 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // analyze later in AST. RecordData DeleteExprsToAnalyze; - for (const auto &DeleteExprsInfo : - SemaRef.getMismatchingDeleteExpressions()) { - AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); - DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); - for (const auto &DeleteLoc : DeleteExprsInfo.second) { - AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); - DeleteExprsToAnalyze.push_back(DeleteLoc.second); + if (!isModule) { + for (const auto &DeleteExprsInfo : + SemaRef.getMismatchingDeleteExpressions()) { + AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); + DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); + for (const auto &DeleteLoc : DeleteExprsInfo.second) { + AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); + DeleteExprsToAnalyze.push_back(DeleteLoc.second); + } } } @@ -4765,7 +4820,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); } } - + auto Abv = std::make_shared<BitCodeAbbrev>(); Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); @@ -4787,7 +4842,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // If we have any extern "C" names, write out a visible update for them. if (Context.ExternCContext) WriteDeclContextVisibleUpdate(Context.ExternCContext); - + // 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? @@ -4826,7 +4881,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, IIs.push_back(II); } // Sort the identifiers to visit based on their name. - std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>()); + llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>()); for (const IdentifierInfo *II : IIs) { for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II), DEnd = SemaRef.IdResolver.end(); @@ -4876,7 +4931,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // declaration-id:i32 // c++-base-specifiers-id:i32 // type-id:i32) - // + // // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule or // MK_ExplicitModule, then the module-name is the module name. Otherwise, // it is the module file name. @@ -4890,7 +4945,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, for (ModuleFile &M : Chain->ModuleMgr) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); LE.write<uint8_t>(static_cast<uint8_t>(M.Kind)); StringRef Name = M.Kind == MK_PrebuiltModule || M.Kind == MK_ExplicitModule @@ -4970,7 +5025,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, WriteOpenCLExtensionDecls(SemaRef); WriteCUDAPragmas(SemaRef); - // If we're emitting a module, write out the submodule information. + // If we're emitting a module, write out the submodule information. if (WritingModule) WriteSubmodules(WritingModule); @@ -5020,7 +5075,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // Write the record containing CUDA-specific declaration references. if (!CUDASpecialDeclRefs.empty()) Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); - + // Write the delegating constructors. if (!DelegatingCtorDecls.empty()) Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); @@ -5063,7 +5118,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, }; // Sort and deduplicate module IDs. - std::sort(Imports.begin(), Imports.end(), Cmp); + llvm::sort(Imports.begin(), Imports.end(), Cmp); Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq), Imports.end()); @@ -5167,6 +5222,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast<CXXRecordDecl>(D); UpdatedDeclContexts.insert(RD->getPrimaryContext()); + Record.push_back(RD->isParamDestroyedInCallee()); + Record.push_back(RD->getArgPassingRestrictions()); Record.AddCXXDefinitionData(RD); Record.AddOffset(WriteDeclContextLexicalBlock( *Context, const_cast<CXXRecordDecl *>(RD))); @@ -5323,7 +5380,7 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { MacroID ASTWriter::getMacroID(MacroInfo *MI) { if (!MI || MI->isBuiltinMacro()) return 0; - + assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); return MacroIDs[MI]; } @@ -5406,12 +5463,11 @@ void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) { return; } + AddTypeRef(TInfo->getType()); AddTypeLoc(TInfo->getTypeLoc()); } void ASTRecordWriter::AddTypeLoc(TypeLoc TL) { - AddTypeRef(TL.getType()); - TypeLocWriter TLW(*this); for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLW.Visit(TL); @@ -5467,12 +5523,12 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { if (!D) { return 0; } - + // If D comes from an AST file, its declaration ID is already known and // fixed. if (D->isFromASTFile()) return D->getGlobalID(); - + assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer"); DeclID &ID = DeclIDs[D]; if (ID == 0) { @@ -5516,7 +5572,9 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { return; // FIXME: ParmVarDecls that are part of a function type of a parameter of // a function/objc method, should not have TU as lexical context. - if (isa<ParmVarDecl>(D)) + // TemplateTemplateParmDecls that are part of an alias template, should not + // have TU as lexical context. + if (isa<ParmVarDecl>(D) || isa<TemplateTemplateParmDecl>(D)) return; SourceManager &SM = Context->getSourceManager(); @@ -5734,6 +5792,7 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); + AddTypeRef(NNS.getTypeLoc().getType()); AddTypeLoc(NNS.getTypeLoc()); AddSourceLocation(NNS.getLocalSourceRange().getEnd()); break; @@ -5792,7 +5851,7 @@ void ASTRecordWriter::AddTemplateName(TemplateName Name) { AddTemplateName(subst->getReplacement()); break; } - + case TemplateName::SubstTemplateTemplateParmPack: { SubstTemplateTemplateParmPackStorage *SubstPack = Name.getAsSubstTemplateTemplateParmPack(); @@ -5855,7 +5914,7 @@ void ASTRecordWriter::AddTemplateParameterList( AddDeclRef(P); } -/// \brief Emit a template argument list. +/// Emit a template argument list. void ASTRecordWriter::AddTemplateArgumentList( const TemplateArgumentList *TemplateArgs) { assert(TemplateArgs && "No TemplateArgs!"); @@ -5892,7 +5951,7 @@ void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) { Record->push_back(Base.getInheritConstructors()); AddTypeSourceInfo(Base.getTypeSourceInfo()); AddSourceRange(Base.getSourceRange()); - AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc() + AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc() : SourceLocation()); } @@ -5965,7 +6024,9 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(Data.Polymorphic); Record->push_back(Data.Abstract); Record->push_back(Data.IsStandardLayout); - Record->push_back(Data.HasNoNonEmptyBases); + Record->push_back(Data.IsCXX11StandardLayout); + Record->push_back(Data.HasBasesWithFields); + Record->push_back(Data.HasBasesWithNonStaticDataMembers); Record->push_back(Data.HasPrivateFields); Record->push_back(Data.HasProtectedFields); Record->push_back(Data.HasPublicFields); @@ -5986,11 +6047,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(Data.DefaultedMoveAssignmentIsDeleted); Record->push_back(Data.DefaultedDestructorIsDeleted); Record->push_back(Data.HasTrivialSpecialMembers); + Record->push_back(Data.HasTrivialSpecialMembersForCall); Record->push_back(Data.DeclaredNonTrivialSpecialMembers); + Record->push_back(Data.DeclaredNonTrivialSpecialMembersForCall); Record->push_back(Data.HasIrrelevantDestructor); Record->push_back(Data.HasConstexprNonCopyMoveConstructor); Record->push_back(Data.HasDefaultedDefaultConstructor); - Record->push_back(Data.CanPassInRegisters); Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr); Record->push_back(Data.HasConstexprDefaultConstructor); Record->push_back(Data.HasNonLiteralTypeFieldsOrBases); @@ -6024,9 +6086,9 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { AddUnresolvedSet(Data.Conversions.get(*Writer->Context)); AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context)); - // Data.Definition is the owning decl, no need to write it. + // Data.Definition is the owning decl, no need to write it. AddDeclRef(D->getFirstFriend()); - + // Add lambda-specific data. if (Data.IsLambda) { auto &Lambda = D->getLambdaData(); @@ -6319,7 +6381,7 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, assert(!WritingAST && "Already writing the AST!"); if (!IFD->isFromASTFile()) return; // Declaration not imported from PCH. - + assert(IFD->getDefinition() && "Category on a class without a definition?"); ObjCClassesWithCategories.insert( const_cast<ObjCInterfaceDecl *>(IFD->getDefinition())); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index bb72a3b383ea8..77e578f6bc57e 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" +#include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/SourceManager.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" @@ -264,7 +265,8 @@ void ASTDeclWriter::Visit(Decl *D) { // abbreviation infrastructure requires that arrays are encoded last, so // we handle it here in the case of those classes derived from DeclaratorDecl if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { - Record.AddTypeSourceInfo(DD->getTypeSourceInfo()); + if (auto *TInfo = DD->getTypeSourceInfo()) + Record.AddTypeLoc(TInfo->getTypeLoc()); } // Handle FunctionDecl's body here and write it after all other Stmts/Exprs @@ -429,6 +431,8 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { Record.push_back(D->isScoped()); Record.push_back(D->isScopedUsingClassTag()); Record.push_back(D->isFixed()); + Record.push_back(D->getODRHash()); + if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); Record.push_back(MemberInfo->getTemplateSpecializationKind()); @@ -465,6 +469,11 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { Record.push_back(D->isAnonymousStructOrUnion()); Record.push_back(D->hasObjectMember()); Record.push_back(D->hasVolatileMember()); + Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize()); + Record.push_back(D->isNonTrivialToPrimitiveCopy()); + Record.push_back(D->isNonTrivialToPrimitiveDestroy()); + Record.push_back(D->isParamDestroyedInCallee()); + Record.push_back(D->getArgPassingRestrictions()); if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && @@ -507,6 +516,9 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) Record.AddQualifierInfo(*D->getExtInfo()); + // The location information is deferred until the end of the record. + Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() + : QualType()); } void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { @@ -528,12 +540,14 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->HasWrittenPrototype); Record.push_back(D->IsDeleted); Record.push_back(D->IsTrivial); + Record.push_back(D->IsTrivialForCall); Record.push_back(D->IsDefaulted); Record.push_back(D->IsExplicitlyDefaulted); Record.push_back(D->HasImplicitReturnZero); Record.push_back(D->IsConstexpr); Record.push_back(D->UsesSEHTry); Record.push_back(D->HasSkippedBody); + Record.push_back(D->IsMultiVersion); Record.push_back(D->IsLateTemplateParsed); Record.push_back(D->getLinkageInternal()); Record.AddSourceLocation(D->getLocEnd()); @@ -912,6 +926,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->isExceptionVariable()); Record.push_back(D->isNRVOVariable()); Record.push_back(D->isCXXForRangeDecl()); + Record.push_back(D->isObjCForDecl()); Record.push_back(D->isARCPseudoStrong()); Record.push_back(D->isInline()); Record.push_back(D->isInlineSpecified()); @@ -1192,6 +1207,7 @@ void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { VisitRedeclarable(D); VisitNamedDecl(D); Record.AddDeclRef(D->getTargetDecl()); + Record.push_back(D->getIdentifierNamespace()); Record.AddDeclRef(D->UsingOrNextShadow); Record.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D)); Code = serialization::DECL_USING_SHADOW; @@ -1625,7 +1641,7 @@ void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { Code = serialization::DECL_STATIC_ASSERT; } -/// \brief Emit the DeclContext part of a declaration context decl. +/// Emit the DeclContext part of a declaration context decl. void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); @@ -1763,11 +1779,11 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable Abv->Add(BitCodeAbbrevOp(0)); // InitStyle // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclFieldAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -1796,6 +1812,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable Abv->Add(BitCodeAbbrevOp(0)); // InitStyle @@ -1803,7 +1820,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclObjCIvarAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -1851,6 +1867,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScoped Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScopedUsingClassTag Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isFixed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));// ODRHash Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedMembEnum // DC Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset @@ -1896,6 +1913,18 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasVolatileMember + + // isNonTrivialToPrimitiveDefaultInitialize + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // isNonTrivialToPrimitiveCopy + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // isNonTrivialToPrimitiveDestroy + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // isParamDestroyedInCallee + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // getArgPassingRestrictions + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); + // DC Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset @@ -1927,6 +1956,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // SClass Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec @@ -1943,7 +1973,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclParmVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2003,6 +2032,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // VarDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec @@ -2011,6 +2041,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isInline Abv->Add(BitCodeAbbrevOp(0)); // isInlineSpecified @@ -2022,7 +2053,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local) Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum) // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2053,6 +2083,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FunctionDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass @@ -2065,12 +2096,14 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd @@ -2162,6 +2195,7 @@ void ASTWriter::WriteDeclAbbrevs() { // CastExpr Abv->Add(BitCodeAbbrevOp(0)); // PathSize Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast // ImplicitCastExpr ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2209,6 +2243,9 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context, } void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { + PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(), + "serializing"); + // Determine the ID for this declaration. serialization::DeclID ID; assert(!D->isFromASTFile() && "should not be emitting imported decl"); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index c5f4495d2f013..3efb6482dd420 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Implements serialization for Statements and Expressions. +/// Implements serialization for Statements and Expressions. /// //===----------------------------------------------------------------------===// @@ -444,6 +444,13 @@ void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { Code = serialization::EXPR_INTEGER_LITERAL; } +void ASTStmtWriter::VisitFixedPointLiteral(FixedPointLiteral *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getLocation()); + Record.AddAPInt(E->getValue()); + Code = serialization::EXPR_INTEGER_LITERAL; +} + void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) { VisitExpr(E); Record.push_back(E->getRawSemantics()); @@ -509,6 +516,7 @@ void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) { Record.AddStmt(E->getSubExpr()); Record.push_back(E->getOpcode()); // FIXME: stable encoding Record.AddSourceLocation(E->getOperatorLoc()); + Record.push_back(E->canOverflow()); Code = serialization::EXPR_UNARY_OPERATOR; } @@ -705,6 +713,7 @@ ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); + Record.push_back(E->isPartOfExplicitCast()); if (E->path_size() == 0) AbbrevToUse = Writer.getExprImplicitCastAbbrev(); @@ -1698,6 +1707,7 @@ void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); Record.AddStmt(E->getSourceExpr()); Record.AddSourceLocation(E->getLocation()); + Record.push_back(E->isUnique()); Code = serialization::EXPR_OPAQUE_VALUE; } @@ -2675,7 +2685,7 @@ void ASTWriter::ClearSwitchCaseIDs() { SwitchCaseIDs.clear(); } -/// \brief Write the given substatement or subexpression to the +/// Write the given substatement or subexpression to the /// bitstream. void ASTWriter::WriteSubStmt(Stmt *S) { RecordData Record; @@ -2719,7 +2729,7 @@ void ASTWriter::WriteSubStmt(Stmt *S) { SubStmtEntries[S] = Offset; } -/// \brief Flush all of the statements that have been added to the +/// Flush all of the statements that have been added to the /// queue via AddStmt(). void ASTRecordWriter::FlushStmts() { // We expect to be the only consumer of the two temporary statement maps, diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp index 20c114297b999..3733638d29778 100644 --- a/lib/Serialization/GlobalModuleIndex.cpp +++ b/lib/Serialization/GlobalModuleIndex.cpp @@ -21,9 +21,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/DJB.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/LockFileManager.h" #include "llvm/Support/MemoryBuffer.h" @@ -38,26 +38,26 @@ using namespace serialization; //----------------------------------------------------------------------------// namespace { enum { - /// \brief The block containing the index. + /// The block containing the index. GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID }; - /// \brief Describes the record types in the index. + /// Describes the record types in the index. enum IndexRecordTypes { - /// \brief Contains version information and potentially other metadata, + /// Contains version information and potentially other metadata, /// used to determine if we can read this global index file. INDEX_METADATA, - /// \brief Describes a module, including its file name and dependencies. + /// Describes a module, including its file name and dependencies. MODULE, - /// \brief The index for identifiers. + /// The index for identifiers. IDENTIFIER_INDEX }; } -/// \brief The name of the global index file. +/// The name of the global index file. static const char * const IndexFileName = "modules.idx"; -/// \brief The global index file version. +/// The global index file version. static const unsigned CurrentVersion = 1; //----------------------------------------------------------------------------// @@ -66,7 +66,7 @@ static const unsigned CurrentVersion = 1; namespace { -/// \brief Trait used to read the identifier index from the on-disk hash +/// Trait used to read the identifier index from the on-disk hash /// table. class IdentifierIndexReaderTrait { public: @@ -81,7 +81,7 @@ public: } static hash_value_type ComputeHash(const internal_key_type& a) { - return llvm::HashString(a); + return llvm::djbHash(a); } static std::pair<unsigned, unsigned> @@ -245,7 +245,7 @@ GlobalModuleIndex::readIndex(StringRef Path) { return std::make_pair(nullptr, EC_NotFound); std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get()); - /// \brief The main bitstream cursor for the main block. + /// The main bitstream cursor for the main block. llvm::BitstreamCursor Cursor(*Buffer); // Sniff for the signature. @@ -289,7 +289,7 @@ void GlobalModuleIndex::getModuleDependencies( bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { Hits.clear(); - + // If there's no identifier index, there is nothing we can do. if (!IdentifierIndex) return false; @@ -368,12 +368,12 @@ LLVM_DUMP_METHOD void GlobalModuleIndex::dump() { //----------------------------------------------------------------------------// namespace { - /// \brief Provides information about a specific module file. + /// Provides information about a specific module file. struct ModuleFileInfo { - /// \brief The numberic ID for this module file. + /// The numberic ID for this module file. unsigned ID; - /// \brief The set of modules on which this module depends. Each entry is + /// The set of modules on which this module depends. Each entry is /// a module ID. SmallVector<unsigned, 4> Dependencies; ASTFileSignature Signature; @@ -387,7 +387,7 @@ namespace { : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {} }; - /// \brief Builder that generates the global module index file. + /// Builder that generates the global module index file. class GlobalModuleIndexBuilder { FileManager &FileMgr; const PCHContainerReader &PCHContainerRdr; @@ -398,26 +398,26 @@ namespace { /// Information about each of the known module files. ModuleFilesMap ModuleFiles; - /// \brief Mapping from the imported module file to the imported + /// Mapping from the imported module file to the imported /// information. typedef std::multimap<const FileEntry *, ImportedModuleFileInfo> ImportedModuleFilesMap; - /// \brief Information about each importing of a module file. + /// Information about each importing of a module file. ImportedModuleFilesMap ImportedModuleFiles; - /// \brief Mapping from identifiers to the list of module file IDs that + /// Mapping from identifiers to the list of module file IDs that /// consider this identifier to be interesting. typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; - /// \brief A mapping from all interesting identifiers to the set of module + /// A mapping from all interesting identifiers to the set of module /// files in which those identifiers are considered interesting. InterestingIdentifierMap InterestingIdentifiers; - - /// \brief Write the block-info block for the global module index file. + + /// Write the block-info block for the global module index file. void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); - /// \brief Retrieve the module file information for the given file. + /// Retrieve the module file information for the given file. ModuleFileInfo &getModuleFileInfo(const FileEntry *File) { llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known = ModuleFiles.find(File); @@ -435,12 +435,12 @@ namespace { FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr) : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {} - /// \brief Load the contents of the given module file into the builder. + /// Load the contents of the given module file into the builder. /// /// \returns true if an error occurred, false otherwise. bool loadModuleFile(const FileEntry *File); - /// \brief Write the index to the given bitstream. + /// Write the index to the given bitstream. /// \returns true if an error occurred, false otherwise. bool writeIndex(llvm::BitstreamWriter &Stream); }; @@ -493,7 +493,7 @@ namespace { : public serialization::reader::ASTIdentifierLookupTraitBase { public: - /// \brief The identifier and whether it is "interesting". + /// The identifier and whether it is "interesting". typedef std::pair<StringRef, bool> data_type; data_type ReadData(const internal_key_type& k, @@ -608,7 +608,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Skip the import location ++Idx; - // Load stored size/modification time. + // Load stored size/modification time. off_t StoredSize = (off_t)Record[Idx++]; time_t StoredModTime = (time_t)Record[Idx++]; @@ -685,7 +685,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { namespace { -/// \brief Trait used to generate the identifier index as an on-disk hash +/// Trait used to generate the identifier index as an on-disk hash /// table. class IdentifierIndexWriterTrait { public: @@ -697,20 +697,20 @@ public: typedef unsigned offset_type; static hash_value_type ComputeHash(key_type_ref Key) { - return llvm::HashString(Key); + return llvm::djbHash(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); + endian::Writer LE(Out, little); unsigned KeyLen = Key.size(); unsigned DataLen = Data.size() * 4; LE.write<uint16_t>(KeyLen); LE.write<uint16_t>(DataLen); return std::make_pair(KeyLen, DataLen); } - + void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { Out.write(Key.data(), KeyLen); } @@ -719,7 +719,7 @@ public: unsigned DataLen) { using namespace llvm::support; for (unsigned I = 0, N = Data.size(); I != N; ++I) - endian::Writer<little>(Out).write<uint32_t>(Data[I]); + endian::write<uint32_t>(Out, Data[I], little); } }; @@ -740,7 +740,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { } using namespace llvm; - + // Emit the file header. Stream.Emit((unsigned)'B', 8); Stream.Emit((unsigned)'C', 8); @@ -789,7 +789,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { I != IEnd; ++I) { Generator.insert(I->first(), I->second, Trait); } - + // Create the on-disk hash table in a buffer. SmallString<4096> IdentifierTable; uint32_t BucketOffset; @@ -797,7 +797,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { using namespace llvm::support; llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 - endian::Writer<little>(Out).write<uint32_t>(0); + endian::write<uint32_t>(Out, 0, little); BucketOffset = Generator.Emit(Out, Trait); } @@ -902,7 +902,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, // Rename the newly-written index file to the proper name. if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { - // Rename failed; just remove the + // Rename failed; just remove the llvm::sys::fs::remove(IndexTmpPath); return EC_IOError; } @@ -913,10 +913,10 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, namespace { class GlobalIndexIdentifierIterator : public IdentifierIterator { - /// \brief The current position within the identifier lookup table. + /// The current position within the identifier lookup table. IdentifierIndexTable::key_iterator Current; - /// \brief The end position within the identifier lookup table. + /// The end position within the identifier lookup table. IdentifierIndexTable::key_iterator End; public: diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp index 5a44d26fe3998..f0ada809ad99e 100644 --- a/lib/Serialization/Module.cpp +++ b/lib/Serialization/Module.cpp @@ -1,4 +1,4 @@ -//===--- Module.cpp - Module description ------------------------*- C++ -*-===// +//===- Module.cpp - Module description ------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,12 @@ // been loaded from an AST file. // //===----------------------------------------------------------------------===// + #include "clang/Serialization/Module.h" #include "ASTReaderInternals.h" +#include "clang/Serialization/ContinuousRangeMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -32,7 +36,8 @@ dumpLocalRemap(StringRef Name, if (Map.begin() == Map.end()) return; - typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType; + using MapType = ContinuousRangeMap<Key, Offset, InitialCapacity>; + llvm::errs() << " " << Name << ":\n"; for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); I != IEnd; ++I) { diff --git a/lib/Serialization/MultiOnDiskHashTable.h b/lib/Serialization/MultiOnDiskHashTable.h index 44d1616a01104..ded7cd1464492 100644 --- a/lib/Serialization/MultiOnDiskHashTable.h +++ b/lib/Serialization/MultiOnDiskHashTable.h @@ -37,7 +37,7 @@ namespace clang { namespace serialization { -/// \brief A collection of on-disk hash tables, merged when relevant for performance. +/// A collection of on-disk hash tables, merged when relevant for performance. template<typename Info> class MultiOnDiskHashTable { public: /// A handle to a file, used when overriding tables. @@ -57,7 +57,7 @@ private: template<typename ReaderInfo, typename WriterInfo> friend class MultiOnDiskHashTableGenerator; - /// \brief A hash table stored on disk. + /// A hash table stored on disk. struct OnDiskTable { using HashTable = llvm::OnDiskIterableChainedHashTable<Info>; @@ -79,14 +79,14 @@ private: using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>; using TableVector = llvm::TinyPtrVector<void *>; - /// \brief The current set of on-disk and merged tables. + /// The current set of on-disk and merged tables. /// We manually store the opaque value of the Table because TinyPtrVector /// can't cope with holding a PointerUnion directly. /// There can be at most one MergedTable in this vector, and if present, /// it is the first table. TableVector Tables; - /// \brief Files corresponding to overridden tables that we've not yet + /// Files corresponding to overridden tables that we've not yet /// discarded. llvm::TinyPtrVector<file_type> PendingOverrides; @@ -102,7 +102,7 @@ private: llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>; using table_range = llvm::iterator_range<table_iterator>; - /// \brief The current set of on-disk tables. + /// The current set of on-disk tables. table_range tables() { auto Begin = Tables.begin(), End = Tables.end(); if (getMergedTable()) @@ -117,7 +117,7 @@ private: .template dyn_cast<MergedTable*>(); } - /// \brief Delete all our current on-disk tables. + /// Delete all our current on-disk tables. void clear() { for (auto *T : tables()) delete T; @@ -194,7 +194,7 @@ public: ~MultiOnDiskHashTable() { clear(); } - /// \brief Add the table \p Data loaded from file \p File. + /// Add the table \p Data loaded from file \p File. void add(file_type File, storage_type Data, Info InfoObj = Info()) { using namespace llvm::support; @@ -225,7 +225,7 @@ public: Tables.push_back(NewTable.getOpaqueValue()); } - /// \brief Find and read the lookup results for \p EKey. + /// Find and read the lookup results for \p EKey. data_type find(const external_key_type &EKey) { data_type Result; @@ -257,7 +257,7 @@ public: return Result; } - /// \brief Read all the lookup results into a single value. This only makes + /// Read all the lookup results into a single value. This only makes /// sense if merging values across keys is meaningful. data_type findAll() { data_type Result; @@ -288,7 +288,7 @@ public: } }; -/// \brief Writer for the on-disk hash table. +/// Writer for the on-disk hash table. template<typename ReaderInfo, typename WriterInfo> class MultiOnDiskHashTableGenerator { using BaseTable = MultiOnDiskHashTable<ReaderInfo>; @@ -312,7 +312,7 @@ public: // Write our header information. { - endian::Writer<little> Writer(OutStream); + endian::Writer Writer(OutStream, little); // Reserve four bytes for the bucket offset. Writer.write<uint32_t>(0); |