diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization')
13 files changed, 3781 insertions, 1724 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp index 445e750..67f74f7 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp @@ -52,8 +52,11 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break; case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break; case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break; + case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break; case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break; case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break; + case BuiltinType::ARCUnbridgedCast: + ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break; case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break; case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break; case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break; diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h index 367f57f..16db8e3 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h @@ -22,7 +22,6 @@ namespace clang { namespace serialization { enum DeclUpdateKind { - UPD_CXX_SET_DEFINITIONDATA, UPD_CXX_ADDED_IMPLICIT_MEMBER, UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index de19d85..f91b66c 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -14,10 +14,9 @@ #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTDeserializationListener.h" #include "clang/Serialization/ModuleManager.h" +#include "clang/Serialization/SerializationDiagnostic.h" #include "ASTCommon.h" #include "ASTReaderInternals.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/Utils.h" #include "clang/Sema/Sema.h" #include "clang/Sema/Scope.h" #include "clang/AST/ASTConsumer.h" @@ -28,6 +27,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" +#include "llvm/Support/SaveAndRestore.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/Preprocessor.h" @@ -64,7 +64,7 @@ ASTReaderListener::~ASTReaderListener() {} bool PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { - const LangOptions &PPLangOpts = PP.getLangOptions(); + const LangOptions &PPLangOpts = PP.getLangOpts(); #define LANGOPT(Name, Bits, Default, Description) \ if (PPLangOpts.Name != LangOpts.Name) { \ @@ -193,9 +193,10 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, // have a #include entry for the PCH file itself (as normalized by the // preprocessor initialization). Find it and skip over it in the checking // below. - llvm::SmallString<256> PCHInclude; + SmallString<256> PCHInclude; PCHInclude += "#include \""; - PCHInclude += NormalizeDashIncludePath(OriginalFileName, FileMgr); + PCHInclude += HeaderSearch::NormalizeDashIncludePath(OriginalFileName, + FileMgr); PCHInclude += "\"\n"; std::pair<StringRef,StringRef> Split = StringRef(PP.getPredefines()).split(PCHInclude.str()); @@ -510,10 +511,13 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // For uninteresting identifiers, just build the IdentifierInfo // and associate it with the persistent ID. IdentifierInfo *II = KnownII; - if (!II) + if (!II) { II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); + KnownII = II; + } Reader.SetIdentifierInfo(ID, II); II->setIsFromAST(); + Reader.markIdentifierUpToDate(II); return II; } @@ -528,8 +532,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, Bits >>= 1; bool hasMacroDefinition = Bits & 0x01; Bits >>= 1; - unsigned ObjCOrBuiltinID = Bits & 0x3FF; - Bits >>= 10; + unsigned ObjCOrBuiltinID = Bits & 0x7FF; + Bits >>= 11; assert(Bits == 0 && "Extra bits in the identifier?"); DataLen -= 6; @@ -537,9 +541,12 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // Build the IdentifierInfo itself and link the identifier ID with // the new IdentifierInfo. IdentifierInfo *II = KnownII; - if (!II) + if (!II) { II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); - Reader.SetIdentifierInfo(ID, II); + KnownII = II; + } + Reader.markIdentifierUpToDate(II); + II->setIsFromAST(); // Set or check the various bits in the IdentifierInfo structure. // Token IDs are read-only. @@ -560,10 +567,32 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, if (hasMacroDefinition) { // FIXME: Check for conflicts? uint32_t Offset = ReadUnalignedLE32(d); - Reader.SetIdentifierIsMacro(II, F, Offset); - DataLen -= 4; + unsigned LocalSubmoduleID = ReadUnalignedLE32(d); + + // Determine whether this macro definition should be visible now, or + // whether it is in a hidden submodule. + bool Visible = true; + if (SubmoduleID GlobalSubmoduleID + = Reader.getGlobalSubmoduleID(F, LocalSubmoduleID)) { + if (Module *Owner = Reader.getSubmodule(GlobalSubmoduleID)) { + if (Owner->NameVisibility == Module::Hidden) { + // The owning module is not visible, and this macro definition should + // not be, either. + Visible = false; + + // Note that this macro definition was hidden because its owning + // module is not yet visible. + Reader.HiddenNamesMap[Owner].push_back(II); + } + } + } + + Reader.setIdentifierIsMacro(II, F, Offset, Visible); + DataLen -= 8; } + Reader.SetIdentifierInfo(ID, II); + // Read all of the declarations visible at global scope with this // name. if (DataLen > 0) { @@ -573,7 +602,6 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, Reader.SetGloballyVisibleDecls(II, DeclIDs); } - II->setIsFromAST(); return II; } @@ -724,11 +752,11 @@ ASTDeclContextNameLookupTrait::ReadData(internal_key_type, unsigned DataLen) { using namespace clang::io; unsigned NumDecls = ReadUnalignedLE16(d); - DeclID *Start = (DeclID *)d; + LE32DeclID *Start = (LE32DeclID *)d; return std::make_pair(Start, Start + NumDecls); } -bool ASTReader::ReadDeclContextStorage(Module &M, +bool ASTReader::ReadDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, const std::pair<uint64_t, uint64_t> &Offsets, DeclContextInfo &Info) { @@ -802,7 +830,7 @@ bool ASTReader::CheckPredefinesBuffers() { /// \brief Read the line table in the source manager block. /// \returns true if there was an error. -bool ASTReader::ParseLineTable(Module &F, +bool ASTReader::ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record) { unsigned Idx = 0; LineTableInfo &LineTable = SourceMgr.getLineTable(); @@ -946,7 +974,7 @@ public: /// \brief Read a source manager block -ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(Module &F) { +ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &F) { using namespace SrcMgr; llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor; @@ -1023,10 +1051,10 @@ resolveFileRelativeToOriginalDir(const std::string &Filename, assert(OriginalDir != CurrDir && "No point trying to resolve the file if the PCH dir didn't change"); using namespace llvm::sys; - llvm::SmallString<128> filePath(Filename); + SmallString<128> filePath(Filename); fs::make_absolute(filePath); assert(path::is_absolute(OriginalDir)); - llvm::SmallString<128> currPCHPath(CurrDir); + SmallString<128> currPCHPath(CurrDir); path::const_iterator fileDirI = path::begin(path::parent_path(filePath)), fileDirE = path::end(path::parent_path(filePath)); @@ -1055,7 +1083,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { return Failure; } - Module *F = GlobalSLocEntryMap.find(-ID)->second; + ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second; F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]); llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; unsigned BaseOffset = F->SLocEntryBaseOffset; @@ -1078,9 +1106,24 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { return Failure; case SM_SLOC_FILE_ENTRY: { - std::string Filename(BlobStart, BlobStart + BlobLen); + if (Record.size() < 7) { + Error("source location entry is incorrect"); + return Failure; + } + + // We will detect whether a file changed and return 'Failure' for it, but + // we will also try to fail gracefully by setting up the SLocEntry. + ASTReader::ASTReadResult Result = Success; + + bool OverriddenBuffer = Record[6]; + + std::string OrigFilename(BlobStart, BlobStart + BlobLen); + std::string Filename = OrigFilename; MaybeAddSystemRootToFilename(Filename); - const FileEntry *File = FileMgr.getFile(Filename); + const FileEntry *File = + OverriddenBuffer? FileMgr.getVirtualFile(Filename, (off_t)Record[4], + (time_t)Record[5]) + : FileMgr.getFile(Filename, /*OpenFile=*/false); if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() && OriginalDir != CurrentDir) { std::string resolved = resolveFileRelativeToOriginalDir(Filename, @@ -1100,11 +1143,6 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { return Failure; } - if (Record.size() < 6) { - Error("source location entry is incorrect"); - return Failure; - } - if (!DisableValidation && ((off_t)Record[4] != File->getSize() #if !defined(LLVM_ON_WIN32) @@ -1115,7 +1153,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { #endif )) { Error(diag::err_fe_pch_file_modified, Filename); - return Failure; + Result = Failure; } SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); @@ -1128,10 +1166,40 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { ID, BaseOffset + Record[0]); SrcMgr::FileInfo &FileInfo = const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); - FileInfo.NumCreatedFIDs = Record[6]; + FileInfo.NumCreatedFIDs = Record[7]; if (Record[3]) FileInfo.setHasLineDirectives(); + + const DeclID *FirstDecl = F->FileSortedDecls + Record[8]; + unsigned NumFileDecls = Record[9]; + if (NumFileDecls) { + assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); + FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl, + NumFileDecls)); + } + const SrcMgr::ContentCache *ContentCache + = SourceMgr.getOrCreateContentCache(File); + if (OverriddenBuffer && !ContentCache->BufferOverridden && + ContentCache->ContentsEntry == ContentCache->OrigEntry) { + unsigned Code = SLocEntryCursor.ReadCode(); + Record.clear(); + unsigned RecCode + = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); + + if (RecCode != SM_SLOC_BUFFER_BLOB) { + Error("AST record has invalid code"); + return Failure; + } + + llvm::MemoryBuffer *Buffer + = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), + Filename); + SourceMgr.overrideFileContents(File, Buffer); + } + + if (Result == Failure) + return Failure; break; } @@ -1149,12 +1217,12 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { } llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), - Name); + = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), + Name); FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, BaseOffset + Offset); - if (strcmp(Name, "<built-in>") == 0) { + if (strcmp(Name, "<built-in>") == 0 && F->Kind == MK_PCH) { PCHPredefinesBlock Block = { BufferID, StringRef(BlobStart, BlobLen - 1) @@ -1181,7 +1249,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { } /// \brief Find the location where the module F is imported. -SourceLocation ASTReader::getImportLocation(Module *F) { +SourceLocation ASTReader::getImportLocation(ModuleFile *F) { if (F->ImportLoc.isValid()) return F->ImportLoc; @@ -1222,7 +1290,7 @@ bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, } } -void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { +void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { llvm::BitstreamCursor &Stream = F.MacroCursor; // Keep track of where we are in the stream, then jump back there @@ -1276,6 +1344,7 @@ void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { Error("macro must have a name in AST file"); return; } + SourceLocation Loc = ReadSourceLocation(F, Record[1]); bool isUsed = Record[2]; @@ -1283,8 +1352,9 @@ void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { MI->setIsUsed(isUsed); MI->setIsFromAST(); - unsigned NextIndex = 3; - MI->setExportLocation(ReadSourceLocation(F, Record, NextIndex)); + bool IsPublic = Record[3]; + unsigned NextIndex = 4; + MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex)); if (RecType == PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. @@ -1304,7 +1374,7 @@ void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { } // Finally, install the macro. - PP.setMacroInfo(II, MI); + PP.setMacroInfo(II, MI, /*LoadedFromAST=*/true); // Remember that we saw this macro last so that we add the tokens that // form its body to it. @@ -1340,14 +1410,12 @@ void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { Macro->AddTokenToBody(Tok); break; } + } } - } - - return; } PreprocessedEntityID -ASTReader::getGlobalPreprocessedEntityID(Module &M, unsigned LocalID) const { +ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const { ContinuousRangeMap<uint32_t, int, 2>::const_iterator I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS); assert(I != M.PreprocessedEntityRemap.end() @@ -1369,14 +1437,13 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) { if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b)) return false; - - // The file names match, but the path names don't. stat() the files to - // see if they are the same. - struct stat StatBufA, StatBufB; - if (StatSimpleCache(a, &StatBufA) || StatSimpleCache(b, &StatBufB)) + + // Determine whether the actual files are equivalent. + bool Result = false; + if (llvm::sys::fs::equivalent(a, b, Result)) return false; - return StatBufA.st_ino == StatBufB.st_ino; + return Result; } std::pair<unsigned, unsigned> @@ -1399,7 +1466,8 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, HFI.Resolved = (Flags >> 1) & 0x01; HFI.IndexHeaderMapHeader = Flags & 0x01; HFI.NumIncludes = ReadUnalignedLE16(d); - HFI.ControllingMacroID = Reader.getGlobalDeclID(M, ReadUnalignedLE32(d)); + HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M, + ReadUnalignedLE32(d)); if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) { // The framework offset is 1 greater than the actual offset, // since 0 is used as an indicator for "no framework name". @@ -1415,10 +1483,12 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, return HFI; } -void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, Module &F, - uint64_t LocalOffset) { - // Note that this identifier has a macro definition. - II->setHasMacroDefinition(true); +void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F, + uint64_t LocalOffset, bool Visible) { + if (Visible) { + // Note that this identifier has a macro definition. + II->setHasMacroDefinition(true); + } // Adjust the offset to a global offset. UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + LocalOffset; @@ -1483,7 +1553,7 @@ void ASTReader::ReadDefinedMacros() { } void ASTReader::LoadMacroDefinition( - llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) { + llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) { assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition"); uint64_t Offset = Pos->second; UnreadMacroRecordOffsets.erase(Pos); @@ -1498,6 +1568,72 @@ void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { LoadMacroDefinition(Pos); } +namespace { + /// \brief Visitor class used to look up identifirs in an AST file. + class IdentifierLookupVisitor { + StringRef Name; + unsigned PriorGeneration; + IdentifierInfo *Found; + public: + IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration) + : Name(Name), PriorGeneration(PriorGeneration), Found() { } + + static bool visit(ModuleFile &M, void *UserData) { + IdentifierLookupVisitor *This + = static_cast<IdentifierLookupVisitor *>(UserData); + + // If we've already searched this module file, skip it now. + if (M.Generation <= This->PriorGeneration) + return true; + + ASTIdentifierLookupTable *IdTable + = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; + if (!IdTable) + return false; + + ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(), + M, This->Found); + + std::pair<const char*, unsigned> Key(This->Name.begin(), + This->Name.size()); + ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Trait); + if (Pos == IdTable->end()) + return false; + + // Dereferencing the iterator has the effect of building the + // IdentifierInfo node and populating it with the various + // declarations it needs. + This->Found = *Pos; + return true; + } + + // \brief Retrieve the identifier info found within the module + // files. + IdentifierInfo *getIdentifierInfo() const { return Found; } + }; +} + +void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { + unsigned PriorGeneration = 0; + if (getContext().getLangOpts().Modules) + PriorGeneration = IdentifierGeneration[&II]; + + IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration); + ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); + markIdentifierUpToDate(&II); +} + +void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { + if (!II) + return; + + II->setOutOfDate(false); + + // Update the generation for this identifier. + if (getContext().getLangOpts().Modules) + IdentifierGeneration[II] = CurrentGeneration; +} + const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { std::string Filename = filenameStrRef; MaybeAddSystemRootToFilename(Filename); @@ -1539,7 +1675,7 @@ void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) { } ASTReader::ASTReadResult -ASTReader::ReadASTBlock(Module &F) { +ASTReader::ReadASTBlock(ModuleFile &F) { llvm::BitstreamCursor &Stream = F.Stream; if (Stream.EnterSubBlock(AST_BLOCK_ID)) { @@ -1608,7 +1744,7 @@ ASTReader::ReadASTBlock(Module &F) { = F.PreprocessorDetailCursor.GetCurrentBitNo(); if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(true); + PP.createPreprocessingRecord(/*RecordConditionalDirectives=*/false); if (!PP.getPreprocessingRecord()->getExternalSource()) PP.getPreprocessingRecord()->SetExternalSource(*this); break; @@ -1626,6 +1762,26 @@ ASTReader::ReadASTBlock(Module &F) { return IgnorePCH; } break; + + case SUBMODULE_BLOCK_ID: + switch (ReadSubmoduleBlock(F)) { + case Success: + break; + + case Failure: + Error("malformed submodule block in AST file"); + return Failure; + + case IgnorePCH: + return IgnorePCH; + } + break; + + default: + if (!Stream.SkipBlock()) + break; + Error("malformed block record in AST file"); + return Failure; } continue; } @@ -1651,6 +1807,12 @@ ASTReader::ReadASTBlock(Module &F) { return IgnorePCH; } + bool hasErrors = Record[5]; + if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) { + Diag(diag::err_pch_with_compiler_errors); + return IgnorePCH; + } + RelocatablePCH = Record[4]; if (Listener) { std::string TargetTriple(BlobStart, BlobLen); @@ -1667,7 +1829,7 @@ ASTReader::ReadASTBlock(Module &F) { // Read information about the AST file. ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; unsigned Length = Record[Idx++]; - llvm::SmallString<128> ImportedFile(Record.begin() + Idx, + SmallString<128> ImportedFile(Record.begin() + Idx, Record.begin() + Idx + Length); Idx += Length; @@ -1697,8 +1859,9 @@ ASTReader::ReadASTBlock(Module &F) { GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F)); // Introduce the local -> global mapping for types within this module. - F.TypeRemap.insert(std::make_pair(LocalBaseTypeIndex, - F.BaseTypeIndex - LocalBaseTypeIndex)); + F.TypeRemap.insertOrReplace( + std::make_pair(LocalBaseTypeIndex, + F.BaseTypeIndex - LocalBaseTypeIndex)); TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes); } @@ -1710,7 +1873,7 @@ ASTReader::ReadASTBlock(Module &F) { Error("duplicate DECL_OFFSET record in AST file"); return Failure; } - F.DeclOffsets = (const uint32_t *)BlobStart; + F.DeclOffsets = (const DeclOffset *)BlobStart; F.LocalNumDecls = Record[0]; unsigned LocalBaseDeclID = Record[1]; F.BaseDeclID = getTotalNumDecls(); @@ -1723,8 +1886,12 @@ ASTReader::ReadASTBlock(Module &F) { // Introduce the local -> global mapping for declarations within this // module. - F.DeclRemap.insert(std::make_pair(LocalBaseDeclID, - F.BaseDeclID - LocalBaseDeclID)); + F.DeclRemap.insertOrReplace( + std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID)); + + // Introduce the global -> local mapping for declarations within this + // module. + F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID; DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); } @@ -1757,16 +1924,6 @@ ASTReader::ReadASTBlock(Module &F) { break; } - case REDECLS_UPDATE_LATEST: { - assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs"); - for (unsigned i = 0, e = Record.size(); i < e; /* in loop */) { - DeclID First = ReadDeclID(F, Record, i); - DeclID Latest = ReadDeclID(F, Record, i); - FirstLatestDeclIDs[First] = Latest; - } - break; - } - case LANGUAGE_OPTIONS: if (ParseLanguageOptions(Record) && !DisableValidation) return IgnorePCH; @@ -1803,9 +1960,9 @@ ASTReader::ReadASTBlock(Module &F) { // Introduce the local -> global mapping for identifiers within this // module. - F.IdentifierRemap.insert( - std::make_pair(LocalBaseIdentifierID, - F.BaseIdentifierID - LocalBaseIdentifierID)); + F.IdentifierRemap.insertOrReplace( + std::make_pair(LocalBaseIdentifierID, + F.BaseIdentifierID - LocalBaseIdentifierID)); IdentifiersLoaded.resize(IdentifiersLoaded.size() + F.LocalNumIdentifiers); @@ -1880,8 +2037,9 @@ ASTReader::ReadASTBlock(Module &F) { // Introduce the local -> global mapping for selectors within this // module. - F.SelectorRemap.insert(std::make_pair(LocalBaseSelectorID, - F.BaseSelectorID - LocalBaseSelectorID)); + F.SelectorRemap.insertOrReplace( + std::make_pair(LocalBaseSelectorID, + F.BaseSelectorID - LocalBaseSelectorID)); SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors); } @@ -1914,6 +2072,10 @@ ASTReader::ReadASTBlock(Module &F) { if (!Record.empty() && Listener) Listener->ReadCounter(Record[0]); break; + + case FILE_SORTED_DECLS: + F.FileSortedDecls = (const DeclID *)BlobStart; + break; case SOURCE_LOCATION_OFFSETS: { F.SLocEntryOffsets = (const uint32_t *)BlobStart; @@ -1959,6 +2121,8 @@ ASTReader::ReadASTBlock(Module &F) { ContinuousRangeMap<uint32_t, int, 2>::Builder PreprocessedEntityRemap(F.PreprocessedEntityRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder + SubmoduleRemap(F.SubmoduleRemap); + ContinuousRangeMap<uint32_t, int, 2>::Builder SelectorRemap(F.SelectorRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap); ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap); @@ -1967,7 +2131,7 @@ ASTReader::ReadASTBlock(Module &F) { uint16_t Len = io::ReadUnalignedLE16(Data); StringRef Name = StringRef((const char*)Data, Len); Data += Len; - Module *OM = ModuleMgr.lookup(Name); + ModuleFile *OM = ModuleMgr.lookup(Name); if (!OM) { Error("SourceLocation remap refers to unknown module"); return Failure; @@ -1976,6 +2140,7 @@ ASTReader::ReadASTBlock(Module &F) { uint32_t SLocOffset = io::ReadUnalignedLE32(Data); uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data); uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data); + uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data); uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data); uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data); uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data); @@ -1989,6 +2154,8 @@ ASTReader::ReadASTBlock(Module &F) { PreprocessedEntityRemap.insert( std::make_pair(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset)); + SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset, + OM->BaseSubmoduleID - SubmoduleIDOffset)); SelectorRemap.insert(std::make_pair(SelectorIDOffset, OM->BaseSelectorID - SelectorIDOffset)); DeclRemap.insert(std::make_pair(DeclIDOffset, @@ -1996,6 +2163,9 @@ ASTReader::ReadASTBlock(Module &F) { TypeRemap.insert(std::make_pair(TypeIndexOffset, OM->BaseTypeIndex - TypeIndexOffset)); + + // Global -> local mappings. + F.GlobalToLocalDeclIDs[OM] = DeclIDOffset; } break; } @@ -2124,7 +2294,7 @@ ASTReader::ReadASTBlock(Module &F) { unsigned StartingID; if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(true); + PP.createPreprocessingRecord(/*RecordConditionalDirectives=*/false); if (!PP.getPreprocessingRecord()->getExternalSource()) PP.getPreprocessingRecord()->SetExternalSource(*this); StartingID @@ -2139,7 +2309,7 @@ ASTReader::ReadASTBlock(Module &F) { // Introduce the local -> global mapping for preprocessed entities in // this module. - F.PreprocessedEntityRemap.insert( + F.PreprocessedEntityRemap.insertOrReplace( std::make_pair(LocalBasePreprocessedEntityID, F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID)); } @@ -2159,30 +2329,31 @@ ASTReader::ReadASTBlock(Module &F) { } case DECL_REPLACEMENTS: { - if (Record.size() % 2 != 0) { + if (Record.size() % 3 != 0) { Error("invalid DECL_REPLACEMENTS block in AST file"); return Failure; } - for (unsigned I = 0, N = Record.size(); I != N; I += 2) + for (unsigned I = 0, N = Record.size(); I != N; I += 3) ReplacedDecls[getGlobalDeclID(F, Record[I])] - = std::make_pair(&F, Record[I+1]); + = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]); break; } - case OBJC_CHAINED_CATEGORIES: { - if (Record.size() % 3 != 0) { - Error("invalid OBJC_CHAINED_CATEGORIES block in AST file"); + case OBJC_CATEGORIES_MAP: { + if (F.LocalNumObjCCategoriesInMap != 0) { + Error("duplicate OBJC_CATEGORIES_MAP record in AST file"); return Failure; } - for (unsigned I = 0, N = Record.size(); I != N; I += 3) { - serialization::GlobalDeclID GlobID = getGlobalDeclID(F, Record[I]); - F.ChainedObjCCategories[GlobID] = std::make_pair(Record[I+1], - Record[I+2]); - ObjCChainedCategoriesInterfaces.insert(GlobID); - } + + F.LocalNumObjCCategoriesInMap = Record[0]; + F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart; break; } + case OBJC_CATEGORIES: + F.ObjCCategories.swap(Record); + break; + case CXX_BASE_SPECIFIER_OFFSETS: { if (F.LocalNumCXXBaseSpecifiers != 0) { Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file"); @@ -2255,13 +2426,52 @@ ASTReader::ReadASTBlock(Module &F) { for (unsigned I = 0, N = Record.size(); I != N; ++I) KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); break; + + case IMPORTED_MODULES: { + if (F.Kind != MK_Module) { + // If we aren't loading a module (which has its own exports), make + // all of the imported modules visible. + // FIXME: Deal with macros-only imports. + for (unsigned I = 0, N = Record.size(); I != N; ++I) { + if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I])) + ImportedModules.push_back(GlobalID); + } + } + break; + } + + case LOCAL_REDECLARATIONS: { + F.RedeclarationChains.swap(Record); + break; + } + + case LOCAL_REDECLARATIONS_MAP: { + if (F.LocalNumRedeclarationsInMap != 0) { + Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file"); + return Failure; + } + + F.LocalNumRedeclarationsInMap = Record[0]; + F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart; + break; + } + + case MERGED_DECLARATIONS: { + for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) { + GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]); + SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID]; + for (unsigned N = Record[Idx++]; N > 0; --N) + Decls.push_back(getGlobalDeclID(F, Record[Idx++])); + } + break; + } } } Error("premature end of bitstream in AST file"); return Failure; } -ASTReader::ASTReadResult ASTReader::validateFileEntries(Module &M) { +ASTReader::ASTReadResult ASTReader::validateFileEntries(ModuleFile &M) { llvm::BitstreamCursor &SLocEntryCursor = M.SLocEntryCursor; for (unsigned i = 0, e = M.LocalNumSLocFileEntries; i != e; ++i) { @@ -2283,6 +2493,10 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(Module &M) { return Failure; case SM_SLOC_FILE_ENTRY: { + // If the buffer was overridden, the file need not exist. + if (Record[6]) + break; + StringRef Filename(BlobStart, BlobLen); const FileEntry *File = getFileEntry(Filename); @@ -2294,7 +2508,7 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(Module &M) { return IgnorePCH; } - if (Record.size() < 6) { + if (Record.size() < 7) { Error("source location entry is incorrect"); return Failure; } @@ -2327,45 +2541,125 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(Module &M) { return Success; } -namespace { - /// \brief Visitor class used to look up identifirs in an AST file. - class IdentifierLookupVisitor { - StringRef Name; - IdentifierInfo *Found; - public: - explicit IdentifierLookupVisitor(StringRef Name) : Name(Name), Found() { } +void ASTReader::makeNamesVisible(const HiddenNames &Names) { + for (unsigned I = 0, N = Names.size(); I != N; ++I) { + if (Decl *D = Names[I].dyn_cast<Decl *>()) + D->Hidden = false; + else { + IdentifierInfo *II = Names[I].get<IdentifierInfo *>(); + if (!II->hasMacroDefinition()) { + II->setHasMacroDefinition(true); + if (DeserializationListener) + DeserializationListener->MacroVisible(II); + } + } + } +} + +void ASTReader::makeModuleVisible(Module *Mod, + Module::NameVisibilityKind NameVisibility) { + llvm::SmallPtrSet<Module *, 4> Visited; + llvm::SmallVector<Module *, 4> Stack; + Stack.push_back(Mod); + while (!Stack.empty()) { + Mod = Stack.back(); + Stack.pop_back(); + + if (NameVisibility <= Mod->NameVisibility) { + // This module already has this level of visibility (or greater), so + // there is nothing more to do. + continue; + } - static bool visit(Module &M, void *UserData) { - IdentifierLookupVisitor *This - = static_cast<IdentifierLookupVisitor *>(UserData); + if (!Mod->isAvailable()) { + // Modules that aren't available cannot be made visible. + continue; + } + + // Update the module's name visibility. + Mod->NameVisibility = NameVisibility; + + // If we've already deserialized any names from this module, + // mark them as visible. + HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod); + if (Hidden != HiddenNamesMap.end()) { + makeNamesVisible(Hidden->second); + HiddenNamesMap.erase(Hidden); + } + + // Push any non-explicit submodules onto the stack to be marked as + // visible. + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) { + if (!(*Sub)->IsExplicit && Visited.insert(*Sub)) + Stack.push_back(*Sub); + } + + // Push any exported modules onto the stack to be marked as visible. + bool AnyWildcard = false; + bool UnrestrictedWildcard = false; + llvm::SmallVector<Module *, 4> WildcardRestrictions; + for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) { + Module *Exported = Mod->Exports[I].getPointer(); + if (!Mod->Exports[I].getInt()) { + // Export a named module directly; no wildcards involved. + if (Visited.insert(Exported)) + Stack.push_back(Exported); + + continue; + } - ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; - if (!IdTable) - return false; + // Wildcard export: export all of the imported modules that match + // the given pattern. + AnyWildcard = true; + if (UnrestrictedWildcard) + continue; + + if (Module *Restriction = Mod->Exports[I].getPointer()) + WildcardRestrictions.push_back(Restriction); + else { + WildcardRestrictions.clear(); + UnrestrictedWildcard = true; + } + } + + // If there were any wildcards, push any imported modules that were + // re-exported by the wildcard restriction. + if (!AnyWildcard) + continue; + + for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) { + Module *Imported = Mod->Imports[I]; + if (Visited.count(Imported)) + continue; - std::pair<const char*, unsigned> Key(This->Name.begin(), - This->Name.size()); - ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key); - if (Pos == IdTable->end()) - return false; + bool Acceptable = UnrestrictedWildcard; + if (!Acceptable) { + // Check whether this module meets one of the restrictions. + for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) { + Module *Restriction = WildcardRestrictions[R]; + if (Imported == Restriction || Imported->isSubModuleOf(Restriction)) { + Acceptable = true; + break; + } + } + } - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - This->Found = *Pos; - return true; + if (!Acceptable) + continue; + + Visited.insert(Imported); + Stack.push_back(Imported); } - - // \brief Retrieve the identifier info found within the module - // files. - IdentifierInfo *getIdentifierInfo() const { return Found; } - }; + } } - ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type) { + // Bump the generation number. + unsigned PreviousGeneration = CurrentGeneration++; + switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) { case Failure: return Failure; case IgnorePCH: return IgnorePCH; @@ -2373,70 +2667,79 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, } // Here comes stuff that we only do once the entire chain is loaded. - + // Check the predefines buffers. - if (!DisableValidation && Type != MK_Module && Type != MK_Preamble && + if (!DisableValidation && Type == MK_PCH && // FIXME: CheckPredefinesBuffers also sets the SuggestedPredefines; // if DisableValidation is true, defines that were set on command-line // but not in the PCH file will not be added to SuggestedPredefines. CheckPredefinesBuffers()) return IgnorePCH; - // Initialization of keywords and pragmas occurs before the - // AST file is read, so there may be some identifiers that were - // loaded into the IdentifierTable before we intercepted the - // creation of identifiers. Iterate through the list of known - // identifiers and determine whether we have to establish - // preprocessor definitions or top-level identifier declaration - // chains for those identifiers. - // - // We copy the IdentifierInfo pointers to a small vector first, - // since de-serializing declarations or macro definitions can add - // new entries into the identifier table, invalidating the - // iterators. - // - // FIXME: We need a lazier way to load this information, e.g., by marking - // the identifier data as 'dirty', so that it will be looked up in the - // AST file(s) if it is uttered in the source. This could save us some - // module load time. - SmallVector<IdentifierInfo *, 128> Identifiers; + // Mark all of the identifiers in the identifier table as being out of date, + // so that various accessors know to check the loaded modules when the + // identifier is used. for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(), IdEnd = PP.getIdentifierTable().end(); Id != IdEnd; ++Id) - Identifiers.push_back(Id->second); + Id->second->setOutOfDate(true); - for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { - IdentifierLookupVisitor Visitor(Identifiers[I]->getName()); - ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); - } + // Resolve any unresolved module exports. + for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) { + UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I]; + SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID); + Module *ResolvedMod = getSubmodule(GlobalID); + + if (Unresolved.IsImport) { + if (ResolvedMod) + Unresolved.Mod->Imports.push_back(ResolvedMod); + continue; + } + if (ResolvedMod || Unresolved.IsWildcard) + Unresolved.Mod->Exports.push_back( + Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard)); + } + UnresolvedModuleImportExports.clear(); + InitializeContext(); if (DeserializationListener) DeserializationListener->ReaderInitialized(this); - // If this AST file is a precompiled preamble, then set the preamble file ID - // of the source manager to the file source file from which the preamble was - // built. - if (Type == MK_Preamble) { - if (!OriginalFileID.isInvalid()) { - OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID - + OriginalFileID.getOpaqueValue() - 1); + if (!OriginalFileID.isInvalid()) { + OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID + + OriginalFileID.getOpaqueValue() - 1); + + // If this AST file is a precompiled preamble, then set the preamble file ID + // of the source manager to the file source file from which the preamble was + // built. + if (Type == MK_Preamble) { SourceMgr.setPreambleFileID(OriginalFileID); + } else if (Type == MK_MainFile) { + SourceMgr.setMainFileID(OriginalFileID); } } + // For any Objective-C class definitions we have already loaded, make sure + // that we load any additional categories. + for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { + loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), + ObjCClassesLoaded[I], + PreviousGeneration); + } + return Success; } ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, - Module *ImportedBy) { - Module *M; + ModuleFile *ImportedBy) { + ModuleFile *M; bool NewModule; std::string ErrorStr; llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy, - ErrorStr); + CurrentGeneration, ErrorStr); if (!M) { // We couldn't load the module. @@ -2458,7 +2761,7 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, if (CurrentDir.empty()) CurrentDir = "."; } - Module &F = *M; + ModuleFile &F = *M; llvm::BitstreamCursor &Stream = F.Stream; Stream.init(F.StreamFile); F.SizeInBits = F.Buffer->getBufferSize() * 8; @@ -2522,7 +2825,7 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, } } - // Once read, set the Module bit base offset and update the size in + // Once read, set the ModuleFile bit base offset and update the size in // bits of all files we've seen. F.GlobalBitOffset = TotalModulesSizeInBits; TotalModulesSizeInBits += F.SizeInBits; @@ -2566,17 +2869,12 @@ void ASTReader::InitializeContext() { // built-in types. Right now, we just ignore the problem. // Load the special types. - if (SpecialTypes.size() > NumSpecialTypeIDs) { + if (SpecialTypes.size() >= NumSpecialTypeIDs) { if (Context.getBuiltinVaListType().isNull()) { Context.setBuiltinVaListType( GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST])); } - if (unsigned Proto = SpecialTypes[SPECIAL_TYPE_OBJC_PROTOCOL]) { - if (Context.ObjCProtoType.isNull()) - Context.ObjCProtoType = GetType(Proto); - } - if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) { if (!Context.CFConstantStringTypeDecl) Context.setCFConstantStringType(GetType(String)); @@ -2603,7 +2901,7 @@ void ASTReader::InitializeContext() { } } - if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_jmp_buf]) { + if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) { QualType Jmp_bufType = GetType(Jmp_buf); if (Jmp_bufType.isNull()) { Error("jmp_buf type is NULL"); @@ -2624,7 +2922,7 @@ void ASTReader::InitializeContext() { } } - if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_sigjmp_buf]) { + if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) { QualType Sigjmp_bufType = GetType(Sigjmp_buf); if (Sigjmp_bufType.isNull()) { Error("sigjmp_buf type is NULL"); @@ -2687,6 +2985,22 @@ void ASTReader::InitializeContext() { Context.setcudaConfigureCallDecl( cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0]))); } + + // Re-export any modules that were imported by a non-module AST file. + for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) { + if (Module *Imported = getSubmodule(ImportedModules[I])) + makeModuleVisible(Imported, Module::AllVisible); + } + ImportedModules.clear(); +} + +void ASTReader::finalizeForWriting() { + for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(), + HiddenEnd = HiddenNamesMap.end(); + Hidden != HiddenEnd; ++Hidden) { + makeNamesVisible(Hidden->second); + } + HiddenNamesMap.clear(); } /// \brief Retrieve the name of the original source file name @@ -2697,7 +3011,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, DiagnosticsEngine &Diags) { // Open the AST file. std::string ErrStr; - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + OwningPtr<llvm::MemoryBuffer> Buffer; Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr)); if (!Buffer) { Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr; @@ -2770,6 +3084,251 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, return std::string(); } +ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { + // Enter the submodule block. + if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) { + Error("malformed submodule block record in AST file"); + return Failure; + } + + ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); + bool First = true; + Module *CurrentModule = 0; + RecordData Record; + while (true) { + unsigned Code = F.Stream.ReadCode(); + if (Code == llvm::bitc::END_BLOCK) { + if (F.Stream.ReadBlockEnd()) { + Error("error at end of submodule block in AST file"); + return Failure; + } + return Success; + } + + if (Code == llvm::bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + F.Stream.ReadSubBlockID(); + if (F.Stream.SkipBlock()) { + Error("malformed block record in AST file"); + return Failure; + } + continue; + } + + if (Code == llvm::bitc::DEFINE_ABBREV) { + F.Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + const char *BlobStart; + unsigned BlobLen; + Record.clear(); + switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + default: // Default behavior: ignore. + break; + + case SUBMODULE_DEFINITION: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (Record.size() < 7) { + Error("malformed module definition"); + return Failure; + } + + StringRef Name(BlobStart, BlobLen); + SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]); + SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]); + bool IsFramework = Record[2]; + bool IsExplicit = Record[3]; + bool IsSystem = Record[4]; + bool InferSubmodules = Record[5]; + bool InferExplicitSubmodules = Record[6]; + bool InferExportWildcard = Record[7]; + + Module *ParentModule = 0; + if (Parent) + ParentModule = getSubmodule(Parent); + + // Retrieve this (sub)module from the module map, creating it if + // necessary. + CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, + IsFramework, + IsExplicit).first; + SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; + if (GlobalIndex >= SubmodulesLoaded.size() || + SubmodulesLoaded[GlobalIndex]) { + Error("too many submodules"); + return Failure; + } + + CurrentModule->IsFromModuleFile = true; + CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; + CurrentModule->InferSubmodules = InferSubmodules; + CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; + CurrentModule->InferExportWildcard = InferExportWildcard; + if (DeserializationListener) + DeserializationListener->ModuleRead(GlobalID, CurrentModule); + + SubmodulesLoaded[GlobalIndex] = CurrentModule; + break; + } + + case SUBMODULE_UMBRELLA_HEADER: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (!CurrentModule) + break; + + StringRef FileName(BlobStart, BlobLen); + if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) { + if (!CurrentModule->getUmbrellaHeader()) + ModMap.setUmbrellaHeader(CurrentModule, Umbrella); + else if (CurrentModule->getUmbrellaHeader() != Umbrella) { + Error("mismatched umbrella headers in submodule"); + return Failure; + } + } + break; + } + + case SUBMODULE_HEADER: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (!CurrentModule) + break; + + // FIXME: Be more lazy about this! + StringRef FileName(BlobStart, BlobLen); + if (const FileEntry *File = PP.getFileManager().getFile(FileName)) { + if (std::find(CurrentModule->Headers.begin(), + CurrentModule->Headers.end(), + File) == CurrentModule->Headers.end()) + ModMap.addHeader(CurrentModule, File); + } + break; + } + + case SUBMODULE_UMBRELLA_DIR: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (!CurrentModule) + break; + + StringRef DirName(BlobStart, BlobLen); + if (const DirectoryEntry *Umbrella + = PP.getFileManager().getDirectory(DirName)) { + if (!CurrentModule->getUmbrellaDir()) + ModMap.setUmbrellaDir(CurrentModule, Umbrella); + else if (CurrentModule->getUmbrellaDir() != Umbrella) { + Error("mismatched umbrella directories in submodule"); + return Failure; + } + } + break; + } + + case SUBMODULE_METADATA: { + if (!First) { + Error("submodule metadata record not at beginning of block"); + return Failure; + } + First = false; + + F.BaseSubmoduleID = getTotalNumSubmodules(); + F.LocalNumSubmodules = Record[0]; + unsigned LocalBaseSubmoduleID = Record[1]; + if (F.LocalNumSubmodules > 0) { + // Introduce the global -> local mapping for submodules within this + // module. + GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F)); + + // Introduce the local -> global mapping for submodules within this + // module. + F.SubmoduleRemap.insertOrReplace( + std::make_pair(LocalBaseSubmoduleID, + F.BaseSubmoduleID - LocalBaseSubmoduleID)); + + SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules); + } + break; + } + + case SUBMODULE_IMPORTS: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (!CurrentModule) + break; + + for (unsigned Idx = 0; Idx != Record.size(); ++Idx) { + UnresolvedModuleImportExport Unresolved; + Unresolved.File = &F; + Unresolved.Mod = CurrentModule; + Unresolved.ID = Record[Idx]; + Unresolved.IsImport = true; + Unresolved.IsWildcard = false; + UnresolvedModuleImportExports.push_back(Unresolved); + } + break; + } + + case SUBMODULE_EXPORTS: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (!CurrentModule) + break; + + for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { + UnresolvedModuleImportExport Unresolved; + Unresolved.File = &F; + Unresolved.Mod = CurrentModule; + Unresolved.ID = Record[Idx]; + Unresolved.IsImport = false; + Unresolved.IsWildcard = Record[Idx + 1]; + UnresolvedModuleImportExports.push_back(Unresolved); + } + + // Once we've loaded the set of exports, there's no reason to keep + // the parsed, unresolved exports around. + CurrentModule->UnresolvedExports.clear(); + break; + } + case SUBMODULE_REQUIRES: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return Failure; + } + + if (!CurrentModule) + break; + + CurrentModule->addRequirement(StringRef(BlobStart, BlobLen), + Context.getLangOpts(), + Context.getTargetInfo()); + break; + } + } + } +} + /// \brief Parse the record that corresponds to a LangOptions data /// structure. /// @@ -2788,20 +3347,31 @@ bool ASTReader::ParseLanguageOptions( LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++])); #include "clang/Basic/LangOptions.def" + unsigned Length = Record[Idx++]; + LangOpts.CurrentModule.assign(Record.begin() + Idx, + Record.begin() + Idx + Length); return Listener->ReadLanguageOptions(LangOpts); } return false; } -PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { - PreprocessedEntityID PPID = Index+1; +std::pair<ModuleFile *, unsigned> +ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) { GlobalPreprocessedEntityMapType::iterator - I = GlobalPreprocessedEntityMap.find(Index); + I = GlobalPreprocessedEntityMap.find(GlobalIndex); assert(I != GlobalPreprocessedEntityMap.end() && "Corrupted global preprocessed entity map"); - Module &M = *I->second; - unsigned LocalIndex = Index - M.BasePreprocessedEntityID; + ModuleFile *M = I->second; + unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID; + return std::make_pair(M, LocalIndex); +} + +PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { + PreprocessedEntityID PPID = Index+1; + std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); + ModuleFile &M = *PPInfo.first; + unsigned LocalIndex = PPInfo.second; const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); @@ -2876,9 +3446,10 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { case PPD_INCLUSION_DIRECTIVE: { const char *FullFileNameStart = BlobStart + Record[0]; - const FileEntry *File - = PP.getFileManager().getFile(StringRef(FullFileNameStart, - BlobLen - Record[0])); + StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]); + const FileEntry *File = 0; + if (!FullFileName.empty()) + File = PP.getFileManager().getFile(FullFileName); // FIXME: Stable encoding InclusionDirective::InclusionKind Kind @@ -2892,9 +3463,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { return ID; } } - - Error("invalid offset in preprocessor detail block"); - return 0; + + llvm_unreachable("Invalid PreprocessorDetailRecordTypes"); } /// \brief \arg SLocMapI points at a chunk of a module that contains no @@ -2906,7 +3476,7 @@ PreprocessedEntityID ASTReader::findNextPreprocessedEntity( ++SLocMapI; for (GlobalSLocOffsetMapType::const_iterator EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) { - Module &M = *SLocMapI->second; + ModuleFile &M = *SLocMapI->second; if (M.NumPreprocessedEntities) return getGlobalPreprocessedEntityID(M, M.BasePreprocessedEntityID); } @@ -2919,9 +3489,9 @@ namespace { template <unsigned PPEntityOffset::*PPLoc> struct PPEntityComp { const ASTReader &Reader; - Module &M; + ModuleFile &M; - PPEntityComp(const ASTReader &Reader, Module &M) : Reader(Reader), M(M) { } + PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { } bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const { SourceLocation LHS = getLoc(L); @@ -2961,7 +3531,7 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { if (SLocMapI->second->NumPreprocessedEntities == 0) return findNextPreprocessedEntity(SLocMapI); - Module &M = *SLocMapI->second; + ModuleFile &M = *SLocMapI->second; typedef const PPEntityOffset *pp_iterator; pp_iterator pp_begin = M.PreprocessedEntityOffsets; pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; @@ -3010,7 +3580,7 @@ ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const { if (SLocMapI->second->NumPreprocessedEntities == 0) return findNextPreprocessedEntity(SLocMapI); - Module &M = *SLocMapI->second; + ModuleFile &M = *SLocMapI->second; typedef const PPEntityOffset *pp_iterator; pp_iterator pp_begin = M.PreprocessedEntityOffsets; pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; @@ -3038,6 +3608,28 @@ std::pair<unsigned, unsigned> return std::make_pair(BeginID, EndID); } +/// \brief Optionally returns true or false if the preallocated preprocessed +/// entity with index \arg Index came from file \arg FID. +llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, + FileID FID) { + if (FID.isInvalid()) + return false; + + std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); + ModuleFile &M = *PPInfo.first; + unsigned LocalIndex = PPInfo.second; + const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; + + SourceLocation Loc = ReadSourceLocation(M, PPOffs.Begin); + if (Loc.isInvalid()) + return false; + + if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID)) + return true; + else + return false; +} + namespace { /// \brief Visitor used to search for information about a header file. class HeaderFileInfoVisitor { @@ -3050,7 +3642,7 @@ namespace { HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE) : Reader(Reader), FE(FE) { } - static bool visit(Module &M, void *UserData) { + static bool visit(ModuleFile &M, void *UserData) { HeaderFileInfoVisitor *This = static_cast<HeaderFileInfoVisitor *>(UserData); @@ -3092,10 +3684,14 @@ HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) { - Module &F = *(*I); + ModuleFile &F = *(*I); unsigned Idx = 0; while (Idx < F.PragmaDiagMappings.size()) { SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]); + Diag.DiagStates.push_back(*Diag.GetCurDiagState()); + Diag.DiagStatePoints.push_back( + DiagnosticsEngine::DiagStatePoint(&Diag.DiagStates.back(), + FullSourceLoc(Loc, SourceMgr))); while (1) { assert(Idx < F.PragmaDiagMappings.size() && "Invalid data, didn't find '-1' marking end of diag/map pairs"); @@ -3108,8 +3704,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { break; // no more diag/map pairs for this location. } diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++]; - // The user bit gets set by WritePragmaDiagnosticMappings. - Diag.setDiagnosticMapping(DiagID, Map, Loc); + DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc); + Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo); } } } @@ -3119,7 +3715,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index); assert(I != GlobalTypeMap.end() && "Corrupted global type map"); - Module *M = I->second; + ModuleFile *M = I->second; return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]); } @@ -3295,14 +3891,15 @@ QualType ASTReader::readTypeRecord(unsigned Index) { ParamTypes.push_back(readType(*Loc.F, Record, Idx)); EPI.Variadic = Record[Idx++]; + EPI.HasTrailingReturn = Record[Idx++]; EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]); ExceptionSpecificationType EST = static_cast<ExceptionSpecificationType>(Record[Idx++]); EPI.ExceptionSpecType = EST; + SmallVector<QualType, 2> Exceptions; if (EST == EST_Dynamic) { EPI.NumExceptions = Record[Idx++]; - SmallVector<QualType, 2> Exceptions; for (unsigned I = 0; I != EPI.NumExceptions; ++I) Exceptions.push_back(readType(*Loc.F, Record, Idx)); EPI.Exceptions = Exceptions.data(); @@ -3344,8 +3941,10 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getTypeOfType(UnderlyingType); } - case TYPE_DECLTYPE: - return Context.getDecltypeType(ReadExpr(*Loc.F)); + case TYPE_DECLTYPE: { + QualType UnderlyingType = readType(*Loc.F, Record, Idx); + return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType); + } case TYPE_UNARY_TRANSFORM: { QualType BaseType = readType(*Loc.F, Record, Idx); @@ -3364,8 +3963,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) { } unsigned Idx = 0; bool IsDependent = Record[Idx++]; - QualType T - = Context.getRecordType(ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx)); + RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx); + RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl()); + QualType T = Context.getRecordType(RD); const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); return T; } @@ -3429,7 +4029,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { unsigned Idx = 0; ObjCInterfaceDecl *ItfD = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx); - return Context.getObjCInterfaceType(ItfD); + return Context.getObjCInterfaceType(ItfD->getCanonicalDecl()); } case TYPE_OBJC_OBJECT: { @@ -3554,13 +4154,12 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getAtomicType(ValueType); } } - // Suppress a GCC warning - return QualType(); + llvm_unreachable("Invalid TypeCode!"); } class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { ASTReader &Reader; - Module &F; + ModuleFile &F; llvm::BitstreamCursor &DeclsCursor; const ASTReader::RecordData &Record; unsigned &Idx; @@ -3576,7 +4175,7 @@ class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { } public: - TypeLocReader(ASTReader &Reader, Module &F, + TypeLocReader(ASTReader &Reader, ModuleFile &F, const ASTReader::RecordData &Record, unsigned &Idx) : Reader(Reader), F(F), DeclsCursor(F.DeclsCursor), Record(Record), Idx(Idx) { } @@ -3733,6 +4332,7 @@ void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc( } void TypeLocReader::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { + TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx)); TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx)); TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); @@ -3747,22 +4347,23 @@ void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { TL.setRParenLoc(ReadSourceLocation(Record, Idx)); } void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); + TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx)); TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); } void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { TL.setNameLoc(ReadSourceLocation(Record, Idx)); } void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); + TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx)); TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); TL.setNameLoc(ReadSourceLocation(Record, Idx)); } void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { - TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); + TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx)); TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); - TL.setNameLoc(ReadSourceLocation(Record, Idx)); + TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx)); + TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx)); TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) @@ -3793,7 +4394,7 @@ void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) { TL.setRParenLoc(ReadSourceLocation(Record, Idx)); } -TypeSourceInfo *ASTReader::GetTypeSourceInfo(Module &F, +TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F, const RecordData &Record, unsigned &Idx) { QualType InfoTy = readType(F, Record, Idx); @@ -3843,6 +4444,7 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break; case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break; case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break; + case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy; break; case PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break; case PREDEF_TYPE_UNKNOWN_ANY: T = Context.UnknownAnyTy; break; case PREDEF_TYPE_NULLPTR_ID: T = Context.NullPtrTy; break; @@ -3856,6 +4458,11 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_AUTO_RREF_DEDUCT: T = Context.getAutoRRefDeductType(); break; + + case PREDEF_TYPE_ARC_UNBRIDGED_CAST: + T = Context.ARCUnbridgedCastTy; + break; + } assert(!T.isNull() && "Unknown predefined type"); @@ -3878,12 +4485,12 @@ QualType ASTReader::GetType(TypeID ID) { return TypesLoaded[Index].withFastQualifiers(FastQuals); } -QualType ASTReader::getLocalType(Module &F, unsigned LocalID) { +QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) { return GetType(getGlobalTypeID(F, LocalID)); } serialization::TypeID -ASTReader::getGlobalTypeID(Module &F, unsigned LocalID) const { +ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const { unsigned FastQuals = LocalID & Qualifiers::FastMask; unsigned LocalIndex = LocalID >> Qualifiers::FastWidth; @@ -3899,7 +4506,7 @@ ASTReader::getGlobalTypeID(Module &F, unsigned LocalID) const { } TemplateArgumentLocInfo -ASTReader::GetTemplateArgumentLocInfo(Module &F, +ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F, TemplateArgument::ArgKind Kind, const RecordData &Record, unsigned &Index) { @@ -3930,11 +4537,10 @@ ASTReader::GetTemplateArgumentLocInfo(Module &F, return TemplateArgumentLocInfo(); } llvm_unreachable("unexpected template argument loc"); - return TemplateArgumentLocInfo(); } TemplateArgumentLoc -ASTReader::ReadTemplateArgumentLoc(Module &F, +ASTReader::ReadTemplateArgumentLoc(ModuleFile &F, const RecordData &Record, unsigned &Index) { TemplateArgument Arg = ReadTemplateArgument(F, Record, Index); @@ -3950,7 +4556,7 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } -uint64_t ASTReader::readCXXBaseSpecifiers(Module &M, const RecordData &Record, +uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, unsigned &Idx){ if (Idx >= Record.size()) return 0; @@ -3983,7 +4589,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { } serialization::DeclID -ASTReader::getGlobalDeclID(Module &F, unsigned LocalID) const { +ASTReader::getGlobalDeclID(ModuleFile &F, unsigned LocalID) const { if (LocalID < NUM_PREDEF_DECL_IDS) return LocalID; @@ -3995,12 +4601,39 @@ ASTReader::getGlobalDeclID(Module &F, unsigned LocalID) const { } bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, - Module &M) const { + ModuleFile &M) const { GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); return &M == I->second; } +ModuleFile *ASTReader::getOwningModuleFile(Decl *D) { + if (!D->isFromASTFile()) + return 0; + GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + return I->second; +} + +SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { + if (ID < NUM_PREDEF_DECL_IDS) + return SourceLocation(); + + unsigned Index = ID - NUM_PREDEF_DECL_IDS; + + if (Index > DeclsLoaded.size()) { + Error("declaration ID out-of-range for AST file"); + return SourceLocation(); + } + + if (Decl *D = DeclsLoaded[Index]) + return D->getLocation(); + + unsigned RawLocation = 0; + RecordLocation Rec = DeclCursorForID(ID, RawLocation); + return ReadSourceLocation(*Rec.F, RawLocation); +} + Decl *ASTReader::GetDecl(DeclID ID) { if (ID < NUM_PREDEF_DECL_IDS) { switch ((PredefinedDeclIDs)ID) { @@ -4019,6 +4652,9 @@ Decl *ASTReader::GetDecl(DeclID ID) { case PREDEF_DECL_OBJC_CLASS_ID: return Context.getObjCClassDecl(); + case PREDEF_DECL_OBJC_PROTOCOL_ID: + return Context.getObjCProtocolDecl(); + case PREDEF_DECL_INT_128_ID: return Context.getInt128Decl(); @@ -4028,18 +4664,15 @@ Decl *ASTReader::GetDecl(DeclID ID) { case PREDEF_DECL_OBJC_INSTANCETYPE_ID: return Context.getObjCInstanceTypeDecl(); } - - return 0; } unsigned Index = ID - NUM_PREDEF_DECL_IDS; - if (Index > DeclsLoaded.size()) { + if (Index >= DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); - return 0; } -if (!DeclsLoaded[Index]) { + if (!DeclsLoaded[Index]) { ReadDeclRecord(ID); if (DeserializationListener) DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); @@ -4048,7 +4681,24 @@ if (!DeclsLoaded[Index]) { return DeclsLoaded[Index]; } -serialization::DeclID ASTReader::ReadDeclID(Module &F, +DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, + DeclID GlobalID) { + if (GlobalID < NUM_PREDEF_DECL_IDS) + return GlobalID; + + GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + ModuleFile *Owner = I->second; + + llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos + = M.GlobalToLocalDeclIDs.find(Owner); + if (Pos == M.GlobalToLocalDeclIDs.end()) + return 0; + + return GlobalID - Owner->BaseDeclID + Pos->second; +} + +serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx) { if (Idx >= Record.size()) { @@ -4093,14 +4743,14 @@ namespace { PredefsVisited[I] = false; } - static bool visit(Module &M, bool Preorder, void *UserData) { + static bool visit(ModuleFile &M, bool Preorder, void *UserData) { if (Preorder) return false; FindExternalLexicalDeclsVisitor *This = static_cast<FindExternalLexicalDeclsVisitor *>(UserData); - Module::DeclContextInfosMap::iterator Info + ModuleFile::DeclContextInfosMap::iterator Info = M.DeclContextInfos.find(This->DC); if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls) return false; @@ -4144,31 +4794,118 @@ ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC, } namespace { - /// \brief Module visitor used to perform name lookup into a + +class DeclIDComp { + ASTReader &Reader; + ModuleFile &Mod; + +public: + DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {} + + bool operator()(LocalDeclID L, LocalDeclID R) const { + SourceLocation LHS = getLocation(L); + SourceLocation RHS = getLocation(R); + return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); + } + + bool operator()(SourceLocation LHS, LocalDeclID R) const { + SourceLocation RHS = getLocation(R); + return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); + } + + bool operator()(LocalDeclID L, SourceLocation RHS) const { + SourceLocation LHS = getLocation(L); + return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); + } + + SourceLocation getLocation(LocalDeclID ID) const { + return Reader.getSourceManager().getFileLoc( + Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID))); + } +}; + +} + +void ASTReader::FindFileRegionDecls(FileID File, + unsigned Offset, unsigned Length, + SmallVectorImpl<Decl *> &Decls) { + SourceManager &SM = getSourceManager(); + + llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File); + if (I == FileDeclIDs.end()) + return; + + FileDeclsInfo &DInfo = I->second; + if (DInfo.Decls.empty()) + return; + + SourceLocation + BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset); + SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length); + + DeclIDComp DIDComp(*this, *DInfo.Mod); + ArrayRef<serialization::LocalDeclID>::iterator + BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(), + BeginLoc, DIDComp); + if (BeginIt != DInfo.Decls.begin()) + --BeginIt; + + // If we are pointing at a top-level decl inside an objc container, we need + // to backtrack until we find it otherwise we will fail to report that the + // region overlaps with an objc container. + while (BeginIt != DInfo.Decls.begin() && + GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt)) + ->isTopLevelDeclInObjCContainer()) + --BeginIt; + + ArrayRef<serialization::LocalDeclID>::iterator + EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(), + EndLoc, DIDComp); + if (EndIt != DInfo.Decls.end()) + ++EndIt; + + for (ArrayRef<serialization::LocalDeclID>::iterator + DIt = BeginIt; DIt != EndIt; ++DIt) + Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt))); +} + +namespace { + /// \brief ModuleFile visitor used to perform name lookup into a /// declaration context. class DeclContextNameLookupVisitor { ASTReader &Reader; + llvm::SmallVectorImpl<const DeclContext *> &Contexts; const DeclContext *DC; DeclarationName Name; SmallVectorImpl<NamedDecl *> &Decls; public: DeclContextNameLookupVisitor(ASTReader &Reader, - const DeclContext *DC, DeclarationName Name, + SmallVectorImpl<const DeclContext *> &Contexts, + DeclarationName Name, SmallVectorImpl<NamedDecl *> &Decls) - : Reader(Reader), DC(DC), Name(Name), Decls(Decls) { } + : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { } - static bool visit(Module &M, void *UserData) { + static bool visit(ModuleFile &M, void *UserData) { DeclContextNameLookupVisitor *This = static_cast<DeclContextNameLookupVisitor *>(UserData); // Check whether we have any visible declaration information for // this context in this module. - Module::DeclContextInfosMap::iterator Info - = M.DeclContextInfos.find(This->DC); - if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData) - return false; + ModuleFile::DeclContextInfosMap::iterator Info; + bool FoundInfo = false; + for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) { + Info = M.DeclContextInfos.find(This->Contexts[I]); + if (Info != M.DeclContextInfos.end() && + Info->second.NameLookupTableData) { + FoundInfo = true; + break; + } + } + if (!FoundInfo) + return false; + // Look for this name within this module. ASTDeclContextNameLookupTable *LookupTable = (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData; @@ -4210,13 +4947,75 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclContext::lookup_iterator(0)); SmallVector<NamedDecl *, 64> Decls; - DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls); + + // Compute the declaration contexts we need to look into. Multiple such + // declaration contexts occur when two declaration contexts from disjoint + // modules get merged, e.g., when two namespaces with the same name are + // independently defined in separate modules. + SmallVector<const DeclContext *, 2> Contexts; + Contexts.push_back(DC); + + if (DC->isNamespace()) { + MergedDeclsMap::iterator Merged + = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); + if (Merged != MergedDecls.end()) { + for (unsigned I = 0, N = Merged->second.size(); I != N; ++I) + Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I]))); + } + } + + DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); ++NumVisibleDeclContextsRead; SetExternalVisibleDeclsForName(DC, Name, Decls); return const_cast<DeclContext*>(DC)->lookup(Name); } +namespace { + /// \brief ModuleFile visitor used to complete the visible decls map of a + /// declaration context. + class DeclContextVisibleDeclMapVisitor { + ASTReader &Reader; + DeclContext *DC; + + public: + DeclContextVisibleDeclMapVisitor(ASTReader &Reader, DeclContext *DC) + : Reader(Reader), DC(DC) { } + + static bool visit(ModuleFile &M, void *UserData) { + return static_cast<DeclContextVisibleDeclMapVisitor*>(UserData)->visit(M); + } + + bool visit(ModuleFile &M) { + // Check whether we have any visible declaration information for + // this context in this module. + ModuleFile::DeclContextInfosMap::iterator + Info = M.DeclContextInfos.find(DC); + if (Info == M.DeclContextInfos.end() || + !Info->second.NameLookupTableData) + return false; + + // Look for this name within this module. + ASTDeclContextNameLookupTable *LookupTable = + (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData; + for (ASTDeclContextNameLookupTable::key_iterator + I = LookupTable->key_begin(), + E = LookupTable->key_end(); I != E; ++I) { + DC->lookup(*I); // Force loading of the visible decls for the decl name. + } + + return false; + } + }; +} + +void ASTReader::completeVisibleDeclsMap(DeclContext *DC) { + if (!DC->hasExternalVisibleStorage()) + return; + DeclContextVisibleDeclMapVisitor Visitor(*this, DC); + ModuleMgr.visit(&DeclContextVisibleDeclMapVisitor::visit, &Visitor); +} + /// \brief 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 @@ -4238,13 +5037,17 @@ void ASTReader::PassInterestingDeclsToConsumer() { Decl *D = InterestingDecls.front(); InterestingDecls.pop_front(); - if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) - PassObjCImplDeclToConsumer(ImplD, Consumer); - else - Consumer->HandleInterestingDecl(DeclGroupRef(D)); + PassInterestingDeclToConsumer(D); } } +void ASTReader::PassInterestingDeclToConsumer(Decl *D) { + if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) + PassObjCImplDeclToConsumer(ImplD, Consumer); + else + Consumer->HandleInterestingDecl(DeclGroupRef(D)); +} + void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) { this->Consumer = Consumer; @@ -4331,15 +5134,15 @@ void ASTReader::PrintStats() { std::fprintf(stderr, "\n"); } -template<typename Key, typename Module, unsigned InitialCapacity> +template<typename Key, typename ModuleFile, unsigned InitialCapacity> static void dumpModuleIDMap(StringRef Name, - const ContinuousRangeMap<Key, Module *, + const ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> &Map) { if (Map.begin() == Map.end()) return; - typedef ContinuousRangeMap<Key, Module *, InitialCapacity> MapType; + typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType; llvm::errs() << Name << ":\n"; for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); I != IEnd; ++I) { @@ -4349,12 +5152,13 @@ dumpModuleIDMap(StringRef Name, } void ASTReader::dump() { - llvm::errs() << "*** PCH/Module Remappings:\n"; + llvm::errs() << "*** PCH/ModuleFile Remappings:\n"; dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap); dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap); dumpModuleIDMap("Global type map", GlobalTypeMap); dumpModuleIDMap("Global declaration map", GlobalDeclMap); dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); + dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); dumpModuleIDMap("Global selector map", GlobalSelectorMap); dumpModuleIDMap("Global preprocessed entity map", GlobalPreprocessedEntityMap); @@ -4392,10 +5196,8 @@ void ASTReader::InitializeSema(Sema &S) { // Makes sure any declarations that were deserialized "too early" // still get added to the identifier's declaration chains. for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) { - if (SemaObj->TUScope) - SemaObj->TUScope->AddDecl(PreloadedDecls[I]); - - SemaObj->IdResolver.AddDecl(PreloadedDecls[I]); + SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I], + PreloadedDecls[I]->getDeclName()); } PreloadedDecls.clear(); @@ -4424,9 +5226,12 @@ void ASTReader::InitializeSema(Sema &S) { } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { - IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart)); + IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart), + /*PriorGeneration=*/0); ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); - return Visitor.getIdentifierInfo(); + IdentifierInfo *II = Visitor.getIdentifierInfo(); + markIdentifierUpToDate(II); + return II; } namespace clang { @@ -4491,45 +5296,27 @@ IdentifierIterator *ASTReader::getIdentifiers() const { namespace clang { namespace serialization { class ReadMethodPoolVisitor { ASTReader &Reader; - Selector Sel; + Selector Sel; + unsigned PriorGeneration; llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods; llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods; - /// \brief Build an ObjCMethodList from a vector of Objective-C method - /// declarations. - ObjCMethodList - buildObjCMethodList(const SmallVectorImpl<ObjCMethodDecl *> &Vec) const - { - ObjCMethodList List; - ObjCMethodList *Prev = 0; - for (unsigned I = 0, N = Vec.size(); I != N; ++I) { - if (!List.Method) { - // This is the first method, which is the easy case. - List.Method = Vec[I]; - Prev = &List; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Vec[I], 0); - Prev = Prev->Next; - } - - return List; - } - public: - ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel) - : Reader(Reader), Sel(Sel) { } + ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, + unsigned PriorGeneration) + : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { } - static bool visit(Module &M, void *UserData) { + static bool visit(ModuleFile &M, void *UserData) { ReadMethodPoolVisitor *This = static_cast<ReadMethodPoolVisitor *>(UserData); if (!M.SelectorLookupTable) return false; + // If we've already searched this module file, skip it now. + if (M.Generation <= This->PriorGeneration) + return true; + ASTSelectorLookupTable *PoolTable = (ASTSelectorLookupTable*)M.SelectorLookupTable; ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel); @@ -4552,28 +5339,50 @@ namespace clang { namespace serialization { } /// \brief Retrieve the instance methods found by this visitor. - ObjCMethodList getInstanceMethods() const { - return buildObjCMethodList(InstanceMethods); + ArrayRef<ObjCMethodDecl *> getInstanceMethods() const { + return InstanceMethods; } /// \brief Retrieve the instance methods found by this visitor. - ObjCMethodList getFactoryMethods() const { - return buildObjCMethodList(FactoryMethods); + ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { + return FactoryMethods; } }; } } // end namespace clang::serialization -std::pair<ObjCMethodList, ObjCMethodList> -ASTReader::ReadMethodPool(Selector Sel) { - ReadMethodPoolVisitor Visitor(*this, Sel); +/// \brief 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) { + S.addMethodToGlobalList(&List, Methods[I]); + } +} + +void ASTReader::ReadMethodPool(Selector Sel) { + // Get the selector generation and update it to the current generation. + unsigned &Generation = SelectorGeneration[Sel]; + unsigned PriorGeneration = Generation; + Generation = CurrentGeneration; + + // Search for methods defined with this selector. + ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration); ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor); - std::pair<ObjCMethodList, ObjCMethodList> Result; - Result.first = Visitor.getInstanceMethods(); - Result.second = Visitor.getFactoryMethods(); - if (!Result.first.Method && !Result.second.Method) + if (Visitor.getInstanceMethods().empty() && + Visitor.getFactoryMethods().empty()) { ++NumMethodPoolMisses; - return Result; + return; + } + + if (!getSema()) + return; + + Sema &S = *getSema(); + Sema::GlobalMethodPool::iterator Pos + = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first; + + addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); + addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); } void ASTReader::ReadKnownNamespaces( @@ -4755,13 +5564,10 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); if (SemaObj) { - if (SemaObj->TUScope) { - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - SemaObj->TUScope->AddDecl(D); - } - SemaObj->IdResolver.AddDeclToIdentifierChain(II, D); + // Introduce this declaration into the translation-unit scope + // and add it to the declaration chain for this identifier, so + // that (unqualified) name lookup will find it. + SemaObj->pushExternalDeclIntoScope(D, II); } else { // Queue this declaration so that it will be added to the // translation unit scope and identifier's declaration chain @@ -4784,7 +5590,7 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { if (!IdentifiersLoaded[ID]) { GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1); assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map"); - Module *M = I->second; + ModuleFile *M = I->second; unsigned Index = ID - M->BaseIdentifierID; const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index]; @@ -4805,11 +5611,11 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { return IdentifiersLoaded[ID]; } -IdentifierInfo *ASTReader::getLocalIdentifier(Module &M, unsigned LocalID) { +IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) { return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID)); } -IdentifierID ASTReader::getGlobalIdentifierID(Module &M, unsigned LocalID) { +IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { if (LocalID < NUM_PREDEF_IDENT_IDS) return LocalID; @@ -4825,7 +5631,34 @@ bool ASTReader::ReadSLocEntry(int ID) { return ReadSLocEntryRecord(ID) != Success; } -Selector ASTReader::getLocalSelector(Module &M, unsigned LocalID) { +serialization::SubmoduleID +ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { + if (LocalID < NUM_PREDEF_SUBMODULE_IDS) + return LocalID; + + ContinuousRangeMap<uint32_t, int, 2>::iterator I + = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS); + assert(I != M.SubmoduleRemap.end() + && "Invalid index into identifier index remap"); + + return LocalID + I->second; +} + +Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { + if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) { + assert(GlobalID == 0 && "Unhandled global submodule ID"); + return 0; + } + + if (GlobalID > SubmodulesLoaded.size()) { + Error("submodule ID out of range in AST file"); + return 0; + } + + return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; +} + +Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { return DecodeSelector(getGlobalSelectorID(M, LocalID)); } @@ -4842,7 +5675,7 @@ Selector ASTReader::DecodeSelector(serialization::SelectorID ID) { // Load this selector from the selector table. GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID); assert(I != GlobalSelectorMap.end() && "Corrupted global selector map"); - Module &M = *I->second; + ModuleFile &M = *I->second; ASTSelectorLookupTrait Trait(*this, M); unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS; SelectorsLoaded[ID - 1] = @@ -4864,7 +5697,7 @@ uint32_t ASTReader::GetNumExternalSelectors() { } serialization::SelectorID -ASTReader::getGlobalSelectorID(Module &M, unsigned LocalID) const { +ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const { if (LocalID < NUM_PREDEF_SELECTOR_IDS) return LocalID; @@ -4877,7 +5710,7 @@ ASTReader::getGlobalSelectorID(Module &M, unsigned LocalID) const { } DeclarationName -ASTReader::ReadDeclarationName(Module &F, +ASTReader::ReadDeclarationName(ModuleFile &F, const RecordData &Record, unsigned &Idx) { DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; switch (Kind) { @@ -4913,11 +5746,10 @@ ASTReader::ReadDeclarationName(Module &F, return DeclarationName::getUsingDirectiveName(); } - // Required to silence GCC warning - return DeclarationName(); + llvm_unreachable("Invalid NameKind!"); } -void ASTReader::ReadDeclarationNameLoc(Module &F, +void ASTReader::ReadDeclarationNameLoc(ModuleFile &F, DeclarationNameLoc &DNLoc, DeclarationName Name, const RecordData &Record, unsigned &Idx) { @@ -4949,7 +5781,7 @@ void ASTReader::ReadDeclarationNameLoc(Module &F, } } -void ASTReader::ReadDeclarationNameInfo(Module &F, +void ASTReader::ReadDeclarationNameInfo(ModuleFile &F, DeclarationNameInfo &NameInfo, const RecordData &Record, unsigned &Idx) { NameInfo.setName(ReadDeclarationName(F, Record, Idx)); @@ -4959,7 +5791,7 @@ void ASTReader::ReadDeclarationNameInfo(Module &F, NameInfo.setInfo(DNLoc); } -void ASTReader::ReadQualifierInfo(Module &F, QualifierInfo &Info, +void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info, const RecordData &Record, unsigned &Idx) { Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); unsigned NumTPLists = Record[Idx++]; @@ -4972,7 +5804,7 @@ void ASTReader::ReadQualifierInfo(Module &F, QualifierInfo &Info, } TemplateName -ASTReader::ReadTemplateName(Module &F, const RecordData &Record, +ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record, unsigned &Idx) { TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; switch (Kind) { @@ -5031,7 +5863,7 @@ ASTReader::ReadTemplateName(Module &F, const RecordData &Record, } TemplateArgument -ASTReader::ReadTemplateArgument(Module &F, +ASTReader::ReadTemplateArgument(ModuleFile &F, const RecordData &Record, unsigned &Idx) { TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++]; switch (Kind) { @@ -5070,7 +5902,7 @@ ASTReader::ReadTemplateArgument(Module &F, } TemplateParameterList * -ASTReader::ReadTemplateParameterList(Module &F, +ASTReader::ReadTemplateParameterList(ModuleFile &F, const RecordData &Record, unsigned &Idx) { SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx); SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx); @@ -5091,7 +5923,7 @@ ASTReader::ReadTemplateParameterList(Module &F, void ASTReader:: ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, - Module &F, const RecordData &Record, + ModuleFile &F, const RecordData &Record, unsigned &Idx) { unsigned NumTemplateArgs = Record[Idx++]; TemplArgs.reserve(NumTemplateArgs); @@ -5100,7 +5932,7 @@ ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, } /// \brief Read a UnresolvedSet structure. -void ASTReader::ReadUnresolvedSet(Module &F, UnresolvedSetImpl &Set, +void ASTReader::ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; while (NumDecls--) { @@ -5111,7 +5943,7 @@ void ASTReader::ReadUnresolvedSet(Module &F, UnresolvedSetImpl &Set, } CXXBaseSpecifier -ASTReader::ReadCXXBaseSpecifier(Module &F, +ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, const RecordData &Record, unsigned &Idx) { bool isVirtual = static_cast<bool>(Record[Idx++]); bool isBaseOfClass = static_cast<bool>(Record[Idx++]); @@ -5127,7 +5959,7 @@ ASTReader::ReadCXXBaseSpecifier(Module &F, } std::pair<CXXCtorInitializer **, unsigned> -ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, +ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx) { CXXCtorInitializer **CtorInitializers = 0; unsigned NumInitializers = Record[Idx++]; @@ -5135,21 +5967,20 @@ ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *BaseClassInfo = 0; + TypeSourceInfo *TInfo = 0; bool IsBaseVirtual = false; FieldDecl *Member = 0; IndirectFieldDecl *IndirectMember = 0; - CXXConstructorDecl *Target = 0; CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; switch (Type) { - case CTOR_INITIALIZER_BASE: - BaseClassInfo = GetTypeSourceInfo(F, Record, Idx); + case CTOR_INITIALIZER_BASE: + TInfo = GetTypeSourceInfo(F, Record, Idx); IsBaseVirtual = Record[Idx++]; break; - - case CTOR_INITIALIZER_DELEGATING: - Target = ReadDeclAs<CXXConstructorDecl>(F, Record, Idx); + + case CTOR_INITIALIZER_DELEGATING: + TInfo = GetTypeSourceInfo(F, Record, Idx); break; case CTOR_INITIALIZER_MEMBER: @@ -5179,12 +6010,12 @@ ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, CXXCtorInitializer *BOMInit; if (Type == CTOR_INITIALIZER_BASE) { - BOMInit = new (Context) CXXCtorInitializer(Context, BaseClassInfo, IsBaseVirtual, + BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init, RParenLoc, MemberOrEllipsisLoc); } else if (Type == CTOR_INITIALIZER_DELEGATING) { - BOMInit = new (Context) CXXCtorInitializer(Context, MemberOrEllipsisLoc, LParenLoc, - Target, Init, RParenLoc); + BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc, + Init, RParenLoc); } else if (IsWritten) { if (Member) BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, @@ -5209,7 +6040,7 @@ ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, } NestedNameSpecifier * -ASTReader::ReadNestedNameSpecifier(Module &F, +ASTReader::ReadNestedNameSpecifier(ModuleFile &F, const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; NestedNameSpecifier *NNS = 0, *Prev = 0; @@ -5258,7 +6089,7 @@ ASTReader::ReadNestedNameSpecifier(Module &F, } NestedNameSpecifierLoc -ASTReader::ReadNestedNameSpecifierLoc(Module &F, const RecordData &Record, +ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; NestedNameSpecifierLocBuilder Builder; @@ -5314,7 +6145,7 @@ ASTReader::ReadNestedNameSpecifierLoc(Module &F, const RecordData &Record, } SourceRange -ASTReader::ReadSourceRange(Module &F, const RecordData &Record, +ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, unsigned &Idx) { SourceLocation beg = ReadSourceLocation(F, Record, Idx); SourceLocation end = ReadSourceLocation(F, Record, Idx); @@ -5361,7 +6192,7 @@ VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, return VersionTuple(Major, Minor - 1, Subminor - 1); } -CXXTemporary *ASTReader::ReadCXXTemporary(Module &F, +CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, const RecordData &Record, unsigned &Idx) { CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx); @@ -5399,10 +6230,8 @@ void ASTReader::ClearSwitchCaseIDs() { SwitchCaseStmts.clear(); } -void ASTReader::FinishedDeserializing() { - assert(NumCurrentElementsDeserializing && - "FinishedDeserializing not paired with StartedDeserializing"); - if (NumCurrentElementsDeserializing == 1) { +void ASTReader::finishPendingActions() { + while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. while (!PendingIdentifierInfos.empty()) { @@ -5410,35 +6239,110 @@ void ASTReader::FinishedDeserializing() { PendingIdentifierInfos.front().DeclIDs, true); PendingIdentifierInfos.pop_front(); } - - // Ready to load previous declarations of Decls that were delayed. - while (!PendingPreviousDecls.empty()) { - loadAndAttachPreviousDecl(PendingPreviousDecls.front().first, - PendingPreviousDecls.front().second); - PendingPreviousDecls.pop_front(); + + // Load pending declaration chains. + for (unsigned I = 0; I != PendingDeclChains.size(); ++I) { + loadPendingDeclChain(PendingDeclChains[I]); + PendingDeclChainsKnown.erase(PendingDeclChains[I]); } + PendingDeclChains.clear(); + } + + // If we deserialized any C++ or Objective-C class definitions, any + // Objective-C protocol definitions, or any redeclarable templates, make sure + // that all redeclarations point to the definitions. Note that this can only + // happen now, after the redeclaration chains have been fully wired. + for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(), + DEnd = PendingDefinitions.end(); + D != DEnd; ++D) { + if (TagDecl *TD = dyn_cast<TagDecl>(*D)) { + if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) { + // Make sure that the TagType points at the definition. + const_cast<TagType*>(TagT)->decl = TD; + } + + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) { + for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(), + REnd = RD->redecls_end(); + R != REnd; ++R) + cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData; + + } - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - if (Consumer) - PassInterestingDeclsToConsumer(); + continue; + } + + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) { + // Make sure that the ObjCInterfaceType points at the definition. + const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl)) + ->Decl = ID; + + for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), + REnd = ID->redecls_end(); + R != REnd; ++R) + R->Data = ID->Data; + + continue; + } + + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) { + for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(), + REnd = PD->redecls_end(); + R != REnd; ++R) + R->Data = PD->Data; + + continue; + } + + RedeclarableTemplateDecl *RTD + = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); + for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(), + REnd = RTD->redecls_end(); + R != REnd; ++R) + R->Common = RTD->Common; + } + PendingDefinitions.clear(); +} - assert(PendingForwardRefs.size() == 0 && - "Some forward refs did not get linked to the definition!"); +void ASTReader::FinishedDeserializing() { + assert(NumCurrentElementsDeserializing && + "FinishedDeserializing not paired with StartedDeserializing"); + if (NumCurrentElementsDeserializing == 1) { + // We decrease NumCurrentElementsDeserializing only after pending actions + // are finished, to avoid recursively re-calling finishPendingActions(). + finishPendingActions(); } --NumCurrentElementsDeserializing; + + if (NumCurrentElementsDeserializing == 0 && + Consumer && !PassingDeclsToConsumer) { + // Guard variable to avoid recursively redoing the process of passing + // decls to consumer. + SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, + true); + + while (!InterestingDecls.empty()) { + // We are not in recursive loading, so it's safe to pass the "interesting" + // decls to the consumer. + Decl *D = InterestingDecls.front(); + InterestingDecls.pop_front(); + PassInterestingDeclToConsumer(D); + } + } } ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, bool DisableValidation, - bool DisableStatCache) + bool DisableStatCache, bool AllowASTWithCompilerErrors) : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), Consumer(0), ModuleMgr(FileMgr.getFileSystemOptions()), RelocatablePCH(false), isysroot(isysroot), DisableValidation(DisableValidation), - DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0), + DisableStatCache(DisableStatCache), + AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), + CurrentGeneration(0), NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), @@ -5446,6 +6350,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), + PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0) { SourceMgr.setExternalSLocEntrySource(this); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index 6cc3f0a..5db5f92 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -14,6 +14,8 @@ #include "ASTCommon.h" #include "clang/Serialization/ASTReader.h" +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -32,9 +34,10 @@ using namespace clang::serialization; namespace clang { class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { ASTReader &Reader; - Module &F; + ModuleFile &F; llvm::BitstreamCursor &Cursor; const DeclID ThisDeclID; + const unsigned RawLocation; typedef ASTReader::RecordData RecordData; const RecordData &Record; unsigned &Idx; @@ -85,24 +88,123 @@ namespace clang { Reader.ReadDeclarationNameInfo(F, NameInfo, R, I); } + serialization::SubmoduleID readSubmoduleID(const RecordData &R, + unsigned &I) { + if (I >= R.size()) + return 0; + + return Reader.getGlobalSubmoduleID(F, R[I++]); + } + + Module *readModule(const RecordData &R, unsigned &I) { + return Reader.getSubmodule(readSubmoduleID(R, I)); + } + void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, const RecordData &R, unsigned &I); - void InitializeCXXDefinitionData(CXXRecordDecl *D, - CXXRecordDecl *DefinitionDecl, - const RecordData &Record, unsigned &Idx); + /// \brief RAII class used to capture the first ID within a redeclaration + /// chain and to introduce it into the list of pending redeclaration chains + /// on destruction. + /// + /// The caller can choose not to introduce this ID into the redeclaration + /// chain by calling \c suppress(). + class RedeclarableResult { + ASTReader &Reader; + GlobalDeclID FirstID; + mutable bool Owning; + + RedeclarableResult &operator=(RedeclarableResult&); // DO NOT IMPLEMENT + + public: + RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID) + : Reader(Reader), FirstID(FirstID), Owning(true) { } + + RedeclarableResult(const RedeclarableResult &Other) + : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) + { + Other.Owning = false; + } + + ~RedeclarableResult() { + // FIXME: We want to suppress this when the declaration is local to + // a function, since there's no reason to search other AST files + // for redeclarations (they can't exist). However, this is hard to + // do locally because the declaration hasn't necessarily loaded its + // declaration context yet. Also, local externs still have the function + // as their (semantic) declaration context, which is wrong and would + // break this optimize. + + if (FirstID && Owning && Reader.PendingDeclChainsKnown.insert(FirstID)) + Reader.PendingDeclChains.push_back(FirstID); + } + + /// \brief Retrieve the first ID. + GlobalDeclID getFirstID() const { return FirstID; } + + /// \brief Do not introduce this declaration ID into the set of pending + /// declaration chains. + void suppress() { + Owning = false; + } + }; + + /// \brief 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; + mutable bool AddResult; + + FindExistingResult &operator=(FindExistingResult&); // DO NOT IMPLEMENT + + public: + FindExistingResult(ASTReader &Reader) + : Reader(Reader), New(0), Existing(0), AddResult(false) { } + + FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing) + : Reader(Reader), New(New), Existing(Existing), AddResult(true) { } + + FindExistingResult(const FindExistingResult &Other) + : Reader(Other.Reader), New(Other.New), Existing(Other.Existing), + AddResult(Other.AddResult) + { + Other.AddResult = false; + } + + ~FindExistingResult(); + + /// \brief Suppress the addition of this result into the known set of + /// names. + void suppress() { AddResult = false; } + + operator NamedDecl*() const { return Existing; } + + template<typename T> + operator T*() const { return dyn_cast_or_null<T>(Existing); } + }; + + FindExistingResult findExisting(NamedDecl *D); + public: - ASTDeclReader(ASTReader &Reader, Module &F, + ASTDeclReader(ASTReader &Reader, ModuleFile &F, llvm::BitstreamCursor &Cursor, DeclID thisDeclID, + unsigned RawLocation, const RecordData &Record, unsigned &Idx) : Reader(Reader), F(F), Cursor(Cursor), ThisDeclID(thisDeclID), - Record(Record), Idx(Idx), TypeIDForTypeDecl(0) { } + RawLocation(RawLocation), Record(Record), Idx(Idx), + TypeIDForTypeDecl(0) { } static void attachPreviousDecl(Decl *D, Decl *previous); + static void attachLatestDecl(Decl *D, Decl *latest); void Visit(Decl *D); - void UpdateDecl(Decl *D, Module &Module, + void UpdateDecl(Decl *D, ModuleFile &ModuleFile, const RecordData &Record); static void setNextObjCCategory(ObjCCategoryDecl *Cat, @@ -118,6 +220,7 @@ namespace clang { void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); + void VisitTypedefNameDecl(TypedefNameDecl *TD); void VisitTypedefDecl(TypedefDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); @@ -148,7 +251,7 @@ namespace clang { void VisitParmVarDecl(ParmVarDecl *PD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); - void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); + RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); @@ -157,6 +260,7 @@ namespace clang { void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); + void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); void VisitFriendDecl(FriendDecl *D); void VisitFriendTemplateDecl(FriendTemplateDecl *D); @@ -164,8 +268,13 @@ namespace clang { void VisitBlockDecl(BlockDecl *BD); std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); - template <typename T> void VisitRedeclarable(Redeclarable<T> *D); + + template<typename T> + RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); + template<typename T> + void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); + // FIXME: Reorder according to DeclNodes.td? void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCContainerDecl(ObjCContainerDecl *D); @@ -173,8 +282,6 @@ namespace clang { void VisitObjCIvarDecl(ObjCIvarDecl *D); void VisitObjCProtocolDecl(ObjCProtocolDecl *D); void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); void VisitObjCCategoryDecl(ObjCCategoryDecl *D); void VisitObjCImplDecl(ObjCImplDecl *D); void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); @@ -207,6 +314,9 @@ void ASTDeclReader::Visit(Decl *D) { if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + // if we have a fully initialized TypeDecl, we can safely read its type now. + ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // FunctionDecl's body was written last after all other Stmts/Exprs. if (Record[Idx++]) @@ -214,12 +324,11 @@ void ASTDeclReader::Visit(Decl *D) { } else if (D->isTemplateParameter()) { // If we have a fully initialized template parameter, we can now // set its DeclContext. - D->setDeclContext( - cast_or_null<DeclContext>( - Reader.GetDecl(DeclContextIDForTemplateParmDecl))); - D->setLexicalDeclContext( - cast_or_null<DeclContext>( - Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl))); + DeclContext *SemaDC = cast<DeclContext>( + Reader.GetDecl(DeclContextIDForTemplateParmDecl)); + DeclContext *LexicalDC = cast<DeclContext>( + Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl)); + D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); } } @@ -233,22 +342,50 @@ void ASTDeclReader::VisitDecl(Decl *D) { LexicalDeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); } else { - D->setDeclContext(ReadDeclAs<DeclContext>(Record, Idx)); - D->setLexicalDeclContext(ReadDeclAs<DeclContext>(Record, Idx)); + DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx); + DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx); + // Avoid calling setLexicalDeclContext() directly because it uses + // Decl::getASTContext() internally which is unsafe during derialization. + D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); } - D->setLocation(ReadSourceLocation(Record, Idx)); + D->setLocation(Reader.ReadSourceLocation(F, RawLocation)); D->setInvalidDecl(Record[Idx++]); if (Record[Idx++]) { // hasAttrs AttrVec Attrs; Reader.ReadAttributes(F, Attrs, Record, Idx); - D->setAttrs(Attrs); + // Avoid calling setAttrs() directly because it uses Decl::getASTContext() + // internally which is unsafe during derialization. + D->setAttrsImpl(Attrs, Reader.getContext()); } D->setImplicit(Record[Idx++]); D->setUsed(Record[Idx++]); D->setReferenced(Record[Idx++]); + D->setTopLevelDeclInObjCContainer(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); D->FromASTFile = true; - D->ModulePrivate = Record[Idx++]; + D->setModulePrivate(Record[Idx++]); + D->Hidden = D->isModulePrivate(); + + // Determine whether this declaration is part of a (sub)module. If so, it + // may not yet be visible. + if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) { + // Store the owning submodule ID in the declaration. + D->setOwningModuleID(SubmoduleID); + + // Module-private declarations are never visible, so there is no work to do. + if (!D->isModulePrivate()) { + if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { + if (Owner->NameVisibility != Module::AllVisible) { + // The owning module is not visible. Mark this declaration as hidden. + D->Hidden = true; + + // Note that this declaration was hidden because its owning module is + // not yet visible. + Reader.HiddenNamesMap[Owner].push_back(D); + } + } + } + } } void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { @@ -267,31 +404,41 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); } -void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { +void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { + RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); + TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + mergeRedeclarable(TD, Redecl); +} + +void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { + VisitTypedefNameDecl(TD); } void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { - VisitTypeDecl(TD); - TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + VisitTypedefNameDecl(TD); } void ASTDeclReader::VisitTagDecl(TagDecl *TD) { + RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); - VisitRedeclarable(TD); + TD->IdentifierNamespace = Record[Idx++]; TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setCompleteDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setFreeStanding(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); + if (Record[Idx++]) { // hasExtInfo TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); TD->TypedefNameDeclOrQualifier = Info; } else TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); + + mergeRedeclarable(TD, Redecl); } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -306,7 +453,13 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ED->IsScoped = Record[Idx++]; ED->IsScopedUsingClassTag = Record[Idx++]; ED->IsFixed = Record[Idx++]; - ED->setInstantiationOfMemberEnum(ReadDeclAs<EnumDecl>(Record, Idx)); + + if (EnumDecl *InstED = ReadDeclAs<EnumDecl>(Record, Idx)) { + TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; + SourceLocation POI = ReadSourceLocation(Record, Idx); + ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK); + ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + } } void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { @@ -340,14 +493,34 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { } void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { + RedeclarableResult Redecl = VisitRedeclarable(FD); VisitDeclaratorDecl(FD); - VisitRedeclarable(FD); ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx); FD->IdentifierNamespace = Record[Idx++]; + + // FunctionDecl's body is handled last at ASTDeclReader::Visit, + // after everything else is read. + + FD->SClass = (StorageClass)Record[Idx++]; + FD->SClassAsWritten = (StorageClass)Record[Idx++]; + FD->IsInline = Record[Idx++]; + FD->IsInlineSpecified = Record[Idx++]; + FD->IsVirtualAsWritten = Record[Idx++]; + FD->IsPure = Record[Idx++]; + FD->HasInheritedPrototype = Record[Idx++]; + FD->HasWrittenPrototype = Record[Idx++]; + FD->IsDeleted = Record[Idx++]; + FD->IsTrivial = Record[Idx++]; + FD->IsDefaulted = Record[Idx++]; + FD->IsExplicitlyDefaulted = Record[Idx++]; + FD->HasImplicitReturnZero = Record[Idx++]; + FD->IsConstexpr = Record[Idx++]; + FD->EndRangeLoc = ReadSourceLocation(Record, Idx); + switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { - default: llvm_unreachable("Unhandled TemplatedKind!"); case FunctionDecl::TK_NonTemplate: + mergeRedeclarable(FD, Redecl); break; case FunctionDecl::TK_FunctionTemplate: FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record, @@ -441,25 +614,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { } } - // FunctionDecl's body is handled last at ASTDeclReader::Visit, - // after everything else is read. - - FD->SClass = (StorageClass)Record[Idx++]; - FD->SClassAsWritten = (StorageClass)Record[Idx++]; - FD->IsInline = Record[Idx++]; - FD->IsInlineSpecified = Record[Idx++]; - FD->IsVirtualAsWritten = Record[Idx++]; - FD->IsPure = Record[Idx++]; - FD->HasInheritedPrototype = Record[Idx++]; - FD->HasWrittenPrototype = Record[Idx++]; - FD->IsDeleted = Record[Idx++]; - FD->IsTrivial = Record[Idx++]; - FD->IsDefaulted = Record[Idx++]; - FD->IsExplicitlyDefaulted = Record[Idx++]; - FD->HasImplicitReturnZero = Record[Idx++]; - FD->IsConstexpr = Record[Idx++]; - FD->EndRangeLoc = ReadSourceLocation(Record, Idx); - // Read in the parameters. unsigned NumParams = Record[Idx++]; SmallVector<ParmVarDecl *, 16> Params; @@ -518,46 +672,60 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { } void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { + RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); - ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull()); - ID->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); - - // Read the directly referenced protocols and their SourceLocations. - unsigned NumProtocols = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - Reader.getContext()); + TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); + mergeRedeclarable(ID, Redecl); - // Read the transitive closure of protocols referenced by this class. - NumProtocols = Record[Idx++]; - Protocols.clear(); - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols, - Reader.getContext()); + if (Record[Idx++]) { + // Read the definition. + ID->allocateDefinitionData(); + + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + ID->getCanonicalDecl()->Data = ID->Data; + + ObjCInterfaceDecl::DefinitionData &Data = ID->data(); + + // Read the superclass. + Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); + Data.SuperClassLoc = ReadSourceLocation(Record, Idx); + + Data.EndLoc = ReadSourceLocation(Record, Idx); + + // Read the directly referenced protocols and their SourceLocations. + unsigned NumProtocols = Record[Idx++]; + SmallVector<ObjCProtocolDecl *, 16> Protocols; + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; + ProtoLocs.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); + ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), + Reader.getContext()); - // Read the ivars. - unsigned NumIvars = Record[Idx++]; - SmallVector<ObjCIvarDecl *, 16> IVars; - IVars.reserve(NumIvars); - for (unsigned I = 0; I != NumIvars; ++I) - IVars.push_back(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); - ID->setCategoryList(ReadDeclAs<ObjCCategoryDecl>(Record, Idx)); + // Read the transitive closure of protocols referenced by this class. + NumProtocols = Record[Idx++]; + Protocols.clear(); + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols, + Reader.getContext()); - // We will rebuild this list lazily. - ID->setIvarList(0); - ID->setForwardDecl(Record[Idx++]); - ID->setImplicitInterfaceDecl(Record[Idx++]); - ID->setSuperClassLoc(ReadSourceLocation(Record, Idx)); - ID->setLocEnd(ReadSourceLocation(Record, Idx)); + // We will rebuild this list lazily. + ID->setIvarList(0); + + // Note that we have deserialized a definition. + Reader.PendingDefinitions.insert(ID); + + // Note that we've loaded this Objective-C class. + Reader.ObjCClassesLoaded.push_back(ID); + } else { + ID->Data = ID->getCanonicalDecl()->Data; + } } void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { @@ -570,50 +738,52 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { + RedeclarableResult Redecl = VisitRedeclarable(PD); VisitObjCContainerDecl(PD); - PD->setForwardDecl(Record[Idx++]); - PD->setLocEnd(ReadSourceLocation(Record, Idx)); - unsigned NumProtoRefs = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - Reader.getContext()); + mergeRedeclarable(PD, Redecl); + + if (Record[Idx++]) { + // Read the definition. + PD->allocateDefinitionData(); + + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + PD->getCanonicalDecl()->Data = PD->Data; + + unsigned NumProtoRefs = Record[Idx++]; + SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; + ProtoRefs.reserve(NumProtoRefs); + for (unsigned I = 0; I != NumProtoRefs; ++I) + ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; + ProtoLocs.reserve(NumProtoRefs); + for (unsigned I = 0; I != NumProtoRefs; ++I) + ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); + PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), + Reader.getContext()); + + // Note that we have deserialized a definition. + Reader.PendingDefinitions.insert(PD); + } else { + PD->Data = PD->getCanonicalDecl()->Data; + } } void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { VisitFieldDecl(FD); } -void ASTDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { - VisitDecl(CD); - ObjCInterfaceDecl *ClassRef = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); - SourceLocation SLoc = ReadSourceLocation(Record, Idx); - CD->setClass(Reader.getContext(), ClassRef, SLoc); -} - -void ASTDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { - VisitDecl(FPD); - unsigned NumProtoRefs = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - Reader.getContext()); -} - void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { VisitObjCContainerDecl(CD); + CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx)); + CD->setIvarLBraceLoc(ReadSourceLocation(Record, Idx)); + CD->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); + + // Note that this category has been deserialized. We do this before + // deserializing the interface declaration, so that it will consider this + /// category. + Reader.CategoriesDeserialized.insert(CD); + CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); unsigned NumProtoRefs = Record[Idx++]; SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; @@ -626,9 +796,7 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), Reader.getContext()); - CD->NextClassCategory = ReadDeclAs<ObjCCategoryDecl>(Record, Idx); CD->setHasSynthBitfield(Record[Idx++]); - CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx)); } void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { @@ -639,6 +807,7 @@ void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { VisitNamedDecl(D); D->setAtLoc(ReadSourceLocation(Record, Idx)); + D->setLParenLoc(ReadSourceLocation(Record, Idx)); D->setType(GetTypeSourceInfo(Record, Idx)); // FIXME: stable encoding D->setPropertyAttributes( @@ -663,11 +832,14 @@ void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { VisitObjCImplDecl(D); D->setIdentifier(Reader.GetIdentifierInfo(F, Record, Idx)); + D->CategoryNameLoc = ReadSourceLocation(Record, Idx); } void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); + D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx)); + D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); llvm::tie(D->IvarInitializers, D->NumIvarInitializers) = Reader.ReadCXXCtorInitializers(F, Record, Idx); D->setHasSynthBitfield(Record[Idx++]); @@ -710,18 +882,30 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { } void ASTDeclReader::VisitVarDecl(VarDecl *VD) { + RedeclarableResult Redecl = VisitRedeclarable(VD); VisitDeclaratorDecl(VD); - VisitRedeclarable(VD); + VD->VarDeclBits.SClass = (StorageClass)Record[Idx++]; VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++]; VD->VarDeclBits.ThreadSpecified = Record[Idx++]; - VD->VarDeclBits.HasCXXDirectInit = Record[Idx++]; + VD->VarDeclBits.InitStyle = Record[Idx++]; VD->VarDeclBits.ExceptionVar = Record[Idx++]; VD->VarDeclBits.NRVOVariable = Record[Idx++]; VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; - if (Record[Idx++]) + + // Only true variables (not parameters or implicit parameters) can be merged. + if (VD->getKind() == Decl::Var) + mergeRedeclarable(VD, Redecl); + + if (uint64_t Val = Record[Idx++]) { VD->setInit(Reader.ReadExpr(F)); + if (Val > 1) { + EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); + Eval->CheckedICE = true; + Eval->IsICE = Val == 3; + } + } if (Record[Idx++]) { // HasMemberSpecializationInfo. VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx); @@ -802,17 +986,25 @@ void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); - D->IsInline = Record[Idx++]; + D->setInline(Record[Idx++]); D->LocStart = ReadSourceLocation(Record, Idx); D->RBraceLoc = ReadSourceLocation(Record, Idx); - D->NextNamespace = Record[Idx++]; - - bool IsOriginal = Record[Idx++]; - // FIXME: Modules will likely have trouble with pointing directly at - // the original namespace. - D->OrigOrAnonNamespace.setInt(IsOriginal); - D->OrigOrAnonNamespace.setPointer(ReadDeclAs<NamespaceDecl>(Record, Idx)); + mergeRedeclarable(D, Redecl); + + if (Redecl.getFirstID() == ThisDeclID) { + // 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 = ReadDeclAs<NamespaceDecl>(Record, Idx); + if (F.Kind != MK_Module) + D->setAnonymousNamespace(Anon); + } else { + // Link this namespace back to the first declaration, which has already + // been deserialized. + D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration()); + } } void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { @@ -828,7 +1020,7 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { D->setUsingLocation(ReadSourceLocation(Record, Idx)); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); - D->FirstUsingShadow = ReadDeclAs<UsingShadowDecl>(Record, Idx); + D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx)); D->setTypeName(Record[Idx++]); if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx)) Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); @@ -869,6 +1061,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( void ASTDeclReader::ReadCXXDefinitionData( struct CXXRecordDecl::DefinitionData &Data, const RecordData &Record, unsigned &Idx) { + // Note: the caller has deserialized the IsLambda bit already. Data.UserDeclaredConstructor = Record[Idx++]; Data.UserDeclaredCopyConstructor = Record[Idx++]; Data.UserDeclaredMoveConstructor = Record[Idx++]; @@ -886,13 +1079,21 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.HasProtectedFields = Record[Idx++]; Data.HasPublicFields = Record[Idx++]; Data.HasMutableFields = Record[Idx++]; + Data.HasOnlyCMembers = Record[Idx++]; Data.HasTrivialDefaultConstructor = Record[Idx++]; Data.HasConstexprNonCopyMoveConstructor = Record[Idx++]; + Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++]; + Data.DefaultedCopyConstructorIsConstexpr = Record[Idx++]; + Data.DefaultedMoveConstructorIsConstexpr = Record[Idx++]; + Data.HasConstexprDefaultConstructor = Record[Idx++]; + Data.HasConstexprCopyConstructor = Record[Idx++]; + Data.HasConstexprMoveConstructor = Record[Idx++]; Data.HasTrivialCopyConstructor = Record[Idx++]; Data.HasTrivialMoveConstructor = Record[Idx++]; Data.HasTrivialCopyAssignment = Record[Idx++]; Data.HasTrivialMoveAssignment = Record[Idx++]; Data.HasTrivialDestructor = Record[Idx++]; + Data.HasIrrelevantDestructor = Record[Idx++]; Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++]; Data.ComputedVisibleConversions = Record[Idx++]; Data.UserProvidedDefaultConstructor = Record[Idx++]; @@ -916,38 +1117,26 @@ void ASTDeclReader::ReadCXXDefinitionData( Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx); assert(Data.Definition && "Data.Definition should be already set!"); Data.FirstFriend = ReadDeclAs<FriendDecl>(Record, Idx); -} - -void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D, - CXXRecordDecl *DefinitionDecl, - const RecordData &Record, - unsigned &Idx) { - ASTContext &C = Reader.getContext(); - - if (D == DefinitionDecl) { - D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); - ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); - // We read the definition info. Check if there are pending forward - // references that need to point to this DefinitionData pointer. - ASTReader::PendingForwardRefsMap::iterator - FindI = Reader.PendingForwardRefs.find(D); - if (FindI != Reader.PendingForwardRefs.end()) { - ASTReader::ForwardRefs &Refs = FindI->second; - for (ASTReader::ForwardRefs::iterator - I = Refs.begin(), E = Refs.end(); I != E; ++I) - (*I)->DefinitionData = D->DefinitionData; -#ifndef NDEBUG - // We later check whether PendingForwardRefs is empty to make sure all - // pending references were linked. - Reader.PendingForwardRefs.erase(D); -#endif - } - } else if (DefinitionDecl) { - if (DefinitionDecl->DefinitionData) { - D->DefinitionData = DefinitionDecl->DefinitionData; - } else { - // The definition is still initializing. - Reader.PendingForwardRefs[DefinitionDecl].push_back(D); + + if (Data.IsLambda) { + typedef LambdaExpr::Capture Capture; + CXXRecordDecl::LambdaDefinitionData &Lambda + = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); + Lambda.Dependent = Record[Idx++]; + Lambda.NumCaptures = Record[Idx++]; + Lambda.NumExplicitCaptures = Record[Idx++]; + Lambda.ManglingNumber = Record[Idx++]; + Lambda.ContextDecl = ReadDecl(Record, Idx); + Lambda.Captures + = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); + Capture *ToCapture = Lambda.Captures; + for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { + SourceLocation Loc = ReadSourceLocation(Record, Idx); + bool IsImplicit = Record[Idx++]; + LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]); + VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx); + SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx); + *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); } } } @@ -955,17 +1144,36 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D, void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { VisitRecordDecl(D); - CXXRecordDecl *DefinitionDecl = ReadDeclAs<CXXRecordDecl>(Record, Idx); - InitializeCXXDefinitionData(D, DefinitionDecl, Record, Idx); - ASTContext &C = Reader.getContext(); + if (Record[Idx++]) { + // Determine whether this is a lambda closure type, so that we can + // allocate the appropriate DefinitionData structure. + bool IsLambda = Record[Idx++]; + if (IsLambda) + D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, false); + else + D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); + + // Propagate the DefinitionData pointer to the canonical declaration, so + // that all other deserialized declarations will see it. + // FIXME: Complain if there already is a DefinitionData! + D->getCanonicalDecl()->DefinitionData = D->DefinitionData; + + ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); + + // Note that we have deserialized a definition. Any declarations + // deserialized before this one will be be given the DefinitionData pointer + // at the end. + Reader.PendingDefinitions.insert(D); + } else { + // Propagate DefinitionData pointer from the canonical declaration. + D->DefinitionData = D->getCanonicalDecl()->DefinitionData; + } enum CXXRecKind { CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization }; switch ((CXXRecKind)Record[Idx++]) { - default: - llvm_unreachable("Out of sync with ASTDeclWriter::VisitCXXRecordDecl?"); case CXXRecNotTemplate: break; case CXXRecTemplate: @@ -1022,6 +1230,16 @@ void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { D->IsExplicitSpecified = Record[Idx++]; } +void ASTDeclReader::VisitImportDecl(ImportDecl *D) { + VisitDecl(D); + D->ImportedAndComplete.setPointer(readModule(Record, Idx)); + D->ImportedAndComplete.setInt(Record[Idx++]); + SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(D + 1); + for (unsigned I = 0, N = Record.back(); I != N; ++I) + StoredLocs[I] = ReadSourceLocation(Record, Idx); + ++Idx; +} + void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { VisitDecl(D); D->setColonLoc(ReadSourceLocation(Record, Idx)); @@ -1061,64 +1279,42 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { D->init(TemplatedDecl, TemplateParams); } -void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - // Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr() - // can be used while this is still initializing. - - assert(D->CommonOrPrev.isNull() && "getCommonPtr was called earlier on this"); - DeclID PreviousDeclID = ReadDeclID(Record, Idx); - DeclID FirstDeclID = PreviousDeclID ? ReadDeclID(Record, Idx) : 0; - // We delay loading of the redeclaration chain to avoid deeply nested calls. - // We temporarily set the first (canonical) declaration as the previous one - // which is the one that matters and mark the real previous DeclID to be - // loaded & attached later on. - RedeclarableTemplateDecl *FirstDecl = - cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(FirstDeclID)); - assert((FirstDecl == 0 || FirstDecl->getKind() == D->getKind()) && - "FirstDecl kind mismatch"); - if (FirstDecl) { - D->CommonOrPrev = FirstDecl; - // Mark the real previous DeclID to be loaded & attached later on. - if (PreviousDeclID != FirstDeclID) - Reader.PendingPreviousDecls.push_back(std::make_pair(D, PreviousDeclID)); - } else { - D->CommonOrPrev = D->newCommon(Reader.getContext()); +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); + + // Make sure we've allocated the Common pointer first. We do this before + // VisitTemplateDecl so that getCommonPtr() can be used during initialization. + RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl(); + if (!CanonD->Common) { + CanonD->Common = CanonD->newCommon(Reader.getContext()); + Reader.PendingDefinitions.insert(CanonD); + } + D->Common = CanonD->Common; + + // 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>(Record, Idx)) { assert(RTD->getKind() == D->getKind() && "InstantiatedFromMemberTemplate kind mismatch"); - D->setInstantiatedFromMemberTemplateImpl(RTD); + D->setInstantiatedFromMemberTemplate(RTD); if (Record[Idx++]) D->setMemberSpecialization(); } - - RedeclarableTemplateDecl *LatestDecl - = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx); - - // This decl is a first one and the latest declaration that it points to is - // in the same AST file. However, if this actually needs to point to a - // redeclaration in another AST file, we need to update it by checking - // the FirstLatestDeclIDs map which tracks this kind of decls. - assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?"); - ASTReader::FirstLatestDeclIDMap::iterator I - = Reader.FirstLatestDeclIDs.find(ThisDeclID); - if (I != Reader.FirstLatestDeclIDs.end()) { - if (Decl *NewLatest = Reader.GetDecl(I->second)) - LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest); - } - - assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch"); - D->getCommonPtr()->Latest = LatestDecl; } - + VisitTemplateDecl(D); D->IdentifierNamespace = Record[Idx++]; + + return Redecl; } void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); - if (D->getPreviousDeclaration() == 0) { + if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. SmallVector<serialization::DeclID, 2> SpecIDs; @@ -1140,6 +1336,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { typedef serialization::DeclID DeclID; ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr(); + // FIXME: Append specializations! CommonPtr->LazySpecializations = new (Reader.getContext()) DeclID [SpecIDs.size()]; memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), @@ -1220,7 +1417,7 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( D->SequenceNumber = Record[Idx++]; // These are read/set from/to the first declaration. - if (D->getPreviousDeclaration() == 0) { + if (D->getPreviousDecl() == 0) { D->InstantiatedFromMember.setPointer( ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx)); D->InstantiatedFromMember.setInt(Record[Idx++]); @@ -1234,9 +1431,9 @@ void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( } void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); - if (D->getPreviousDeclaration() == 0) { + if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. // Read the function specialization declarations. @@ -1311,54 +1508,90 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { } template <typename T> -void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { - enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; - RedeclKind Kind = (RedeclKind)Record[Idx++]; - switch (Kind) { - default: - llvm_unreachable("Out of sync with ASTDeclWriter::VisitRedeclarable or" - " messed up reading"); - case NoRedeclaration: - break; - case PointsToPrevious: { - DeclID PreviousDeclID = ReadDeclID(Record, Idx); - DeclID FirstDeclID = ReadDeclID(Record, Idx); +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { + DeclID FirstDeclID = ReadDeclID(Record, Idx); + + // 0 indicates that this declaration was the only declaration of its entity, + // and is used for space optimization. + if (FirstDeclID == 0) + FirstDeclID = ThisDeclID; + + T *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 // which is the one that matters and mark the real previous DeclID to be // loaded & attached later on. - D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink( - cast_or_null<T>(Reader.GetDecl(FirstDeclID))); - if (PreviousDeclID != FirstDeclID) - Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D), - PreviousDeclID)); - break; - } - case PointsToLatest: - D->RedeclLink = typename Redeclarable<T>::LatestDeclLink( - ReadDeclAs<T>(Record, Idx)); - break; - } - - assert(!(Kind == PointsToPrevious && - Reader.FirstLatestDeclIDs.find(ThisDeclID) != - Reader.FirstLatestDeclIDs.end()) && - "This decl is not first, it should not be in the map"); - if (Kind == PointsToPrevious) + D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl); + } + + // Note that this declaration has been deserialized. + Reader.RedeclsDeserialized.insert(static_cast<T *>(D)); + + // The result structure takes care to note that we need to load the + // other declaration chains for this ID. + return RedeclarableResult(Reader, FirstDeclID); +} + +/// \brief Attempts to merge the given declaration (D) with another declaration +/// of the same entity. +template<typename T> +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, + RedeclarableResult &Redecl) { + // If modules are not available, there is no reason to perform this merge. + if (!Reader.getContext().getLangOpts().Modules) return; - - // This decl is a first one and the latest declaration that it points to is in - // the same AST file. However, if this actually needs to point to a - // redeclaration in another AST file, we need to update it by checking the - // FirstLatestDeclIDs map which tracks this kind of decls. - assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) && - "Invalid ThisDeclID ?"); - ASTReader::FirstLatestDeclIDMap::iterator I - = Reader.FirstLatestDeclIDs.find(ThisDeclID); - if (I != Reader.FirstLatestDeclIDs.end()) { - Decl *NewLatest = Reader.GetDecl(I->second); - D->RedeclLink - = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest)); + + if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) { + if (T *Existing = ExistingRes) { + T *ExistingCanon = Existing->getCanonicalDecl(); + T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); + if (ExistingCanon != DCanon) { + // Have our redeclaration link point back at the canonical declaration + // of the existing declaration, so that this declaration has the + // appropriate canonical declaration. + D->RedeclLink + = typename Redeclarable<T>::PreviousDeclLink(ExistingCanon); + + // When we merge a namespace, update its pointer to the first namespace. + if (NamespaceDecl *Namespace + = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) { + Namespace->AnonOrFirstNamespaceAndInline.setPointer( + static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon))); + } + + // Don't introduce DCanon into the set of pending declaration chains. + Redecl.suppress(); + + // Introduce ExistingCanon into the set of pending declaration chains, + // if in fact it came from a module file. + if (ExistingCanon->isFromASTFile()) { + GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID(); + assert(ExistingCanonID && "Unrecorded canonical declaration ID?"); + if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID)) + Reader.PendingDeclChains.push_back(ExistingCanonID); + } + + // If this declaration was the canonical declaration, make a note of + // that. We accept the linear algorithm here because the number of + // unique canonical declarations of an entity should always be tiny. + if (DCanon == static_cast<T*>(D)) { + SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; + if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) + == Merged.end()) + Merged.push_back(Redecl.getFirstID()); + + // If ExistingCanon did not come from a module file, introduce the + // first declaration that *does* come from a module file to the + // set of pending declaration chains, so that we merge this + // declaration. + if (!ExistingCanon->isFromASTFile() && + Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID())) + Reader.PendingDeclChains.push_back(Merged[0]); + } + } + } } } @@ -1367,7 +1600,7 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { //===----------------------------------------------------------------------===// /// \brief Reads attributes from the current stream position. -void ASTReader::ReadAttributes(Module &F, AttrVec &Attrs, +void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs, const RecordData &Record, unsigned &Idx) { for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) { Attr *New = 0; @@ -1422,31 +1655,142 @@ static bool isConsumerInterestedIn(Decl *D) { /// \brief Get the correct cursor and offset for loading a declaration. ASTReader::RecordLocation -ASTReader::DeclCursorForID(DeclID ID) { +ASTReader::DeclCursorForID(DeclID ID, unsigned &RawLocation) { // See if there's an override. DeclReplacementMap::iterator It = ReplacedDecls.find(ID); - if (It != ReplacedDecls.end()) - return RecordLocation(It->second.first, It->second.second); + if (It != ReplacedDecls.end()) { + RawLocation = It->second.RawLoc; + return RecordLocation(It->second.Mod, It->second.Offset); + } GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - Module *M = I->second; - return RecordLocation(M, - M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]); + ModuleFile *M = I->second; + const DeclOffset & + DOffs = M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; + RawLocation = DOffs.Loc; + return RecordLocation(M, DOffs.BitOffset); } ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) { - ContinuousRangeMap<uint64_t, Module*, 4>::iterator I + ContinuousRangeMap<uint64_t, ModuleFile*, 4>::iterator I = GlobalBitOffsetsMap.find(GlobalOffset); assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map"); return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset); } -uint64_t ASTReader::getGlobalBitOffset(Module &M, uint32_t LocalOffset) { +uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { return LocalOffset + M.GlobalBitOffset; } +/// \brief Determine whether the two declarations refer to the same entity. +static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { + assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); + + if (X == Y) + return true; + + // Must be in the same context. + if (!X->getDeclContext()->getRedeclContext()->Equals( + Y->getDeclContext()->getRedeclContext())) + 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)) + return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), + TypedefY->getUnderlyingType()); + + // Must have the same kind. + if (X->getKind() != Y->getKind()) + return false; + + // Objective-C classes and protocols with the same name always match. + if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) + return true; + + // Compatible tags match. + if (TagDecl *TagX = dyn_cast<TagDecl>(X)) { + TagDecl *TagY = cast<TagDecl>(Y); + return (TagX->getTagKind() == TagY->getTagKind()) || + ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class) && + (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class)); + } + + // Functions with the same type and linkage match. + // FIXME: This needs to cope with function templates, merging of + //prototyped/non-prototyped functions, etc. + if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { + FunctionDecl *FuncY = cast<FunctionDecl>(Y); + return (FuncX->getLinkage() == FuncY->getLinkage()) && + FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType()); + } + + // Variables with the same type and linkage match. + if (VarDecl *VarX = dyn_cast<VarDecl>(X)) { + VarDecl *VarY = cast<VarDecl>(Y); + return (VarX->getLinkage() == VarY->getLinkage()) && + VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType()); + } + + // Namespaces with the same name and inlinedness match. + if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) { + NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y); + return NamespaceX->isInline() == NamespaceY->isInline(); + } + + // FIXME: Many other cases to implement. + return false; +} + +ASTDeclReader::FindExistingResult::~FindExistingResult() { + if (!AddResult || Existing) + return; + + DeclContext *DC = New->getDeclContext()->getRedeclContext(); + if (DC->isTranslationUnit() && Reader.SemaObj) { + Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName()); + } else if (DC->isNamespace()) { + DC->addDecl(New); + } +} + +ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + if (!Name) { + // Don't bother trying to find unnamed declarations. + FindExistingResult Result(Reader, D, /*Existing=*/0); + Result.suppress(); + return Result; + } + + DeclContext *DC = D->getDeclContext()->getRedeclContext(); + if (!DC->isFileContext()) + return FindExistingResult(Reader); + + if (DC->isTranslationUnit() && Reader.SemaObj) { + IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; + for (IdentifierResolver::iterator I = IdResolver.begin(Name), + IEnd = IdResolver.end(); + I != IEnd; ++I) { + if (isSameEntity(*I, D)) + return FindExistingResult(Reader, D, *I); + } + } + + if (DC->isNamespace()) { + for (DeclContext::lookup_result R = DC->lookup(Name); + R.first != R.second; ++R.first) { + if (isSameEntity(*R.first, D)) + return FindExistingResult(Reader, D, *R.first); + } + } + + return FindExistingResult(Reader, D, /*Existing=*/0); +} + void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { assert(D && previous); if (TagDecl *TD = dyn_cast<TagDecl>(D)) { @@ -1455,12 +1799,78 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { FD->RedeclLink.setPointer(cast<FunctionDecl>(previous)); } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { VD->RedeclLink.setPointer(cast<VarDecl>(previous)); + } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + TD->RedeclLink.setPointer(cast<TypedefNameDecl>(previous)); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous)); + } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + PD->RedeclLink.setPointer(cast<ObjCProtocolDecl>(previous)); + } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { + ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous)); } else { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); - TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous); + TD->RedeclLink.setPointer(cast<RedeclarableTemplateDecl>(previous)); } } +void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { + assert(D && Latest); + if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + TD->RedeclLink + = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest)); + } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + FD->RedeclLink + = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest)); + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + VD->RedeclLink + = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest)); + } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + TD->RedeclLink + = Redeclarable<TypedefNameDecl>::LatestDeclLink( + cast<TypedefNameDecl>(Latest)); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + ID->RedeclLink + = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink( + cast<ObjCInterfaceDecl>(Latest)); + } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + PD->RedeclLink + = Redeclarable<ObjCProtocolDecl>::LatestDeclLink( + cast<ObjCProtocolDecl>(Latest)); + } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { + ND->RedeclLink + = Redeclarable<NamespaceDecl>::LatestDeclLink( + cast<NamespaceDecl>(Latest)); + } else { + RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); + TD->RedeclLink + = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink( + cast<RedeclarableTemplateDecl>(Latest)); + } +} + +ASTReader::MergedDeclsMap::iterator +ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { + // If we don't have any stored merged declarations, just look in the + // merged declarations set. + StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID); + if (StoredPos == StoredMergedDecls.end()) + return MergedDecls.find(Canon); + + // Append the stored merged declarations to the merged declarations set. + MergedDeclsMap::iterator Pos = MergedDecls.find(Canon); + if (Pos == MergedDecls.end()) + Pos = MergedDecls.insert(std::make_pair(Canon, + SmallVector<DeclID, 2>())).first; + Pos->second.append(StoredPos->second.begin(), StoredPos->second.end()); + StoredMergedDecls.erase(StoredPos); + + // Sort and uniquify the set of merged declarations. + llvm::array_pod_sort(Pos->second.begin(), Pos->second.end()); + Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()), + Pos->second.end()); + return Pos; +} + void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { Decl *previous = GetDecl(ID); ASTDeclReader::attachPreviousDecl(D, previous); @@ -1469,7 +1879,8 @@ void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { /// \brief Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned Index = ID - NUM_PREDEF_DECL_IDS; - RecordLocation Loc = DeclCursorForID(ID); + unsigned RawLocation = 0; + RecordLocation Loc = DeclCursorForID(ID, RawLocation); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; // Keep track of where we are in the stream, then jump back there // after reading this declaration. @@ -1484,7 +1895,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { RecordData Record; unsigned Code = DeclsCursor.ReadCode(); unsigned Idx = 0; - ASTDeclReader Reader(*this, *Loc.F, DeclsCursor, ID, Record, Idx); + ASTDeclReader Reader(*this, *Loc.F, DeclsCursor, ID, RawLocation, Record,Idx); Decl *D = 0; switch ((DeclCode)DeclsCursor.ReadRecord(Code, Record)) { @@ -1492,222 +1903,177 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CONTEXT_VISIBLE: llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord"); case DECL_TYPEDEF: - D = TypedefDecl::Create(Context, 0, SourceLocation(), SourceLocation(), - 0, 0); + D = TypedefDecl::CreateDeserialized(Context, ID); break; case DECL_TYPEALIAS: - D = TypeAliasDecl::Create(Context, 0, SourceLocation(), SourceLocation(), - 0, 0); + D = TypeAliasDecl::CreateDeserialized(Context, ID); break; case DECL_ENUM: - D = EnumDecl::Create(Context, Decl::EmptyShell()); + D = EnumDecl::CreateDeserialized(Context, ID); break; case DECL_RECORD: - D = RecordDecl::Create(Context, Decl::EmptyShell()); + D = RecordDecl::CreateDeserialized(Context, ID); break; case DECL_ENUM_CONSTANT: - D = EnumConstantDecl::Create(Context, 0, SourceLocation(), 0, QualType(), - 0, llvm::APSInt()); + D = EnumConstantDecl::CreateDeserialized(Context, ID); break; case DECL_FUNCTION: - D = FunctionDecl::Create(Context, 0, SourceLocation(), SourceLocation(), - DeclarationName(), QualType(), 0); + D = FunctionDecl::CreateDeserialized(Context, ID); break; case DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::Create(Context, 0, SourceLocation(), SourceLocation(), - (LinkageSpecDecl::LanguageIDs)0, - SourceLocation()); + D = LinkageSpecDecl::CreateDeserialized(Context, ID); break; case DECL_LABEL: - D = LabelDecl::Create(Context, 0, SourceLocation(), 0); + D = LabelDecl::CreateDeserialized(Context, ID); break; case DECL_NAMESPACE: - D = NamespaceDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), 0); + D = NamespaceDecl::CreateDeserialized(Context, ID); break; case DECL_NAMESPACE_ALIAS: - D = NamespaceAliasDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), 0, - NestedNameSpecifierLoc(), - SourceLocation(), 0); + D = NamespaceAliasDecl::CreateDeserialized(Context, ID); break; case DECL_USING: - D = UsingDecl::Create(Context, 0, SourceLocation(), - NestedNameSpecifierLoc(), DeclarationNameInfo(), - false); + D = UsingDecl::CreateDeserialized(Context, ID); break; case DECL_USING_SHADOW: - D = UsingShadowDecl::Create(Context, 0, SourceLocation(), 0, 0); + D = UsingShadowDecl::CreateDeserialized(Context, ID); break; case DECL_USING_DIRECTIVE: - D = UsingDirectiveDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), NestedNameSpecifierLoc(), - SourceLocation(), 0, 0); + D = UsingDirectiveDecl::CreateDeserialized(Context, ID); break; case DECL_UNRESOLVED_USING_VALUE: - D = UnresolvedUsingValueDecl::Create(Context, 0, SourceLocation(), - NestedNameSpecifierLoc(), - DeclarationNameInfo()); + D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID); break; case DECL_UNRESOLVED_USING_TYPENAME: - D = UnresolvedUsingTypenameDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), - NestedNameSpecifierLoc(), - SourceLocation(), - DeclarationName()); + D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID); break; case DECL_CXX_RECORD: - D = CXXRecordDecl::Create(Context, Decl::EmptyShell()); + D = CXXRecordDecl::CreateDeserialized(Context, ID); break; case DECL_CXX_METHOD: - D = CXXMethodDecl::Create(Context, 0, SourceLocation(), - DeclarationNameInfo(), QualType(), 0, - false, SC_None, false, false, SourceLocation()); + D = CXXMethodDecl::CreateDeserialized(Context, ID); break; case DECL_CXX_CONSTRUCTOR: - D = CXXConstructorDecl::Create(Context, Decl::EmptyShell()); + D = CXXConstructorDecl::CreateDeserialized(Context, ID); break; case DECL_CXX_DESTRUCTOR: - D = CXXDestructorDecl::Create(Context, Decl::EmptyShell()); + D = CXXDestructorDecl::CreateDeserialized(Context, ID); break; case DECL_CXX_CONVERSION: - D = CXXConversionDecl::Create(Context, Decl::EmptyShell()); + D = CXXConversionDecl::CreateDeserialized(Context, ID); break; case DECL_ACCESS_SPEC: - D = AccessSpecDecl::Create(Context, Decl::EmptyShell()); + D = AccessSpecDecl::CreateDeserialized(Context, ID); break; case DECL_FRIEND: - D = FriendDecl::Create(Context, Decl::EmptyShell()); + D = FriendDecl::CreateDeserialized(Context, ID); break; case DECL_FRIEND_TEMPLATE: - D = FriendTemplateDecl::Create(Context, Decl::EmptyShell()); + D = FriendTemplateDecl::CreateDeserialized(Context, ID); break; case DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::Create(Context, Decl::EmptyShell()); + D = ClassTemplateDecl::CreateDeserialized(Context, ID); break; case DECL_CLASS_TEMPLATE_SPECIALIZATION: - D = ClassTemplateSpecializationDecl::Create(Context, Decl::EmptyShell()); + D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID); break; case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: - D = ClassTemplatePartialSpecializationDecl::Create(Context, - Decl::EmptyShell()); + D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); break; case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: - D = ClassScopeFunctionSpecializationDecl::Create(Context, - Decl::EmptyShell()); + D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID); break; case DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::Create(Context, Decl::EmptyShell()); + D = FunctionTemplateDecl::CreateDeserialized(Context, ID); break; case DECL_TEMPLATE_TYPE_PARM: - D = TemplateTypeParmDecl::Create(Context, Decl::EmptyShell()); + D = TemplateTypeParmDecl::CreateDeserialized(Context, ID); break; case DECL_NON_TYPE_TEMPLATE_PARM: - D = NonTypeTemplateParmDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), 0, 0, 0, QualType(), - false, 0); + D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID); break; case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: - D = NonTypeTemplateParmDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), 0, 0, 0, QualType(), - 0, 0, Record[Idx++], 0); + D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, Record[Idx++]); break; case DECL_TEMPLATE_TEMPLATE_PARM: - D = TemplateTemplateParmDecl::Create(Context, 0, SourceLocation(), 0, 0, - false, 0, 0); + D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID); break; case DECL_TYPE_ALIAS_TEMPLATE: - D = TypeAliasTemplateDecl::Create(Context, Decl::EmptyShell()); + D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID); break; case DECL_STATIC_ASSERT: - D = StaticAssertDecl::Create(Context, 0, SourceLocation(), 0, 0, - SourceLocation()); + D = StaticAssertDecl::CreateDeserialized(Context, ID); break; - case DECL_OBJC_METHOD: - D = ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(), - Selector(), QualType(), 0, 0); + D = ObjCMethodDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::Create(Context, 0, SourceLocation(), 0); + D = ObjCInterfaceDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_IVAR: - D = ObjCIvarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, ObjCIvarDecl::None); + D = ObjCIvarDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_PROTOCOL: - D = ObjCProtocolDecl::Create(Context, 0, 0, SourceLocation(), - SourceLocation()); + D = ObjCProtocolDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), 0, QualType(), 0); - break; - case DECL_OBJC_CLASS: - D = ObjCClassDecl::Create(Context, 0, SourceLocation()); - break; - case DECL_OBJC_FORWARD_PROTOCOL: - D = ObjCForwardProtocolDecl::Create(Context, 0, SourceLocation()); + D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_CATEGORY: - D = ObjCCategoryDecl::Create(Context, Decl::EmptyShell()); + D = ObjCCategoryDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_CATEGORY_IMPL: - D = ObjCCategoryImplDecl::Create(Context, 0, 0, 0, SourceLocation(), - SourceLocation()); + D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_IMPLEMENTATION: - D = ObjCImplementationDecl::Create(Context, 0, 0, 0, SourceLocation(), - SourceLocation()); + D = ObjCImplementationDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_COMPATIBLE_ALIAS: - D = ObjCCompatibleAliasDecl::Create(Context, 0, SourceLocation(), 0, 0); + D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_PROPERTY: - D = ObjCPropertyDecl::Create(Context, 0, SourceLocation(), 0, SourceLocation(), - 0); + D = ObjCPropertyDecl::CreateDeserialized(Context, ID); break; case DECL_OBJC_PROPERTY_IMPL: - D = ObjCPropertyImplDecl::Create(Context, 0, SourceLocation(), - SourceLocation(), 0, - ObjCPropertyImplDecl::Dynamic, 0, - SourceLocation()); + D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID); break; case DECL_FIELD: - D = FieldDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, 0, false, false); + D = FieldDecl::CreateDeserialized(Context, ID); break; case DECL_INDIRECTFIELD: - D = IndirectFieldDecl::Create(Context, 0, SourceLocation(), 0, QualType(), - 0, 0); + D = IndirectFieldDecl::CreateDeserialized(Context, ID); break; case DECL_VAR: - D = VarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, SC_None, SC_None); + D = VarDecl::CreateDeserialized(Context, ID); break; - case DECL_IMPLICIT_PARAM: - D = ImplicitParamDecl::Create(Context, 0, SourceLocation(), 0, QualType()); + D = ImplicitParamDecl::CreateDeserialized(Context, ID); break; - case DECL_PARM_VAR: - D = ParmVarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, SC_None, SC_None, 0); + D = ParmVarDecl::CreateDeserialized(Context, ID); break; case DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::Create(Context, 0, 0, SourceLocation(), - SourceLocation()); + D = FileScopeAsmDecl::CreateDeserialized(Context, ID); break; case DECL_BLOCK: - D = BlockDecl::Create(Context, 0, SourceLocation()); + D = BlockDecl::CreateDeserialized(Context, ID); break; case DECL_CXX_BASE_SPECIFIERS: Error("attempt to read a C++ base-specifier record as a declaration"); return 0; + case DECL_IMPORT: + // Note: last entry of the ImportDecl record is the number of stored source + // locations. + D = ImportDecl::CreateDeserialized(Context, ID, Record.back()); + break; } assert(D && "Unknown declaration reading AST file"); LoadedDecl(Index, D); + // Set the DeclContext before doing any deserialization, to make sure internal + // calls to Decl::getASTContext() by Decl's methods will find the + // TranslationUnitDecl without crashing. + D->setDeclContext(Context.getTranslationUnitDecl()); Reader.Visit(D); // If this declaration is also a declaration context, get the @@ -1743,16 +2109,18 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // Load any relevant update records. loadDeclUpdateRecords(ID, D); - - if (ObjCChainedCategoriesInterfaces.count(ID)) - loadObjCChainedCategories(ID, cast<ObjCInterfaceDecl>(D)); + + // Load the categories after recursive loading is finished. + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) + if (Class->isThisDeclarationADefinition()) + loadObjCCategories(ID, Class); // If we have deserialized a declaration that has a definition the // AST consumer might need to know about, queue it. // We don't pass it to the consumer immediately because we may be in recursive // loading, and some declarations may still be initializing. if (isConsumerInterestedIn(D)) - InterestingDecls.push_back(D); + InterestingDecls.push_back(D); return D; } @@ -1766,7 +2134,7 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { FileOffsetsTy &UpdateOffsets = UpdI->second; for (FileOffsetsTy::iterator I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { - Module *F = I->first; + ModuleFile *F = I->first; uint64_t Offset = I->second; llvm::BitstreamCursor &Cursor = F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); @@ -1778,179 +2146,328 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); unsigned Idx = 0; - ASTDeclReader Reader(*this, *F, Cursor, ID, Record, Idx); + ASTDeclReader Reader(*this, *F, Cursor, ID, 0, Record, Idx); Reader.UpdateDecl(D, *F, Record); } } } namespace { - /// \brief Given an ObjC interface, goes through the modules and links to the - /// interface all the categories for it. - class ObjCChainedCategoriesVisitor { - ASTReader &Reader; - serialization::GlobalDeclID InterfaceID; - ObjCInterfaceDecl *Interface; - ObjCCategoryDecl *GlobHeadCat, *GlobTailCat; - llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; - - public: - ObjCChainedCategoriesVisitor(ASTReader &Reader, - serialization::GlobalDeclID InterfaceID, - ObjCInterfaceDecl *Interface) - : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface), - GlobHeadCat(0), GlobTailCat(0) { } - - static bool visit(Module &M, void *UserData) { - return static_cast<ObjCChainedCategoriesVisitor *>(UserData)->visit(M); + struct CompareLocalRedeclarationsInfoToID { + bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) { + return X.FirstID < Y; } - bool visit(Module &M) { - if (Reader.isDeclIDFromModule(InterfaceID, M)) - return true; // We reached the module where the interface originated - // from. Stop traversing the imported modules. + bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) { + return X < Y.FirstID; + } - Module::ChainedObjCCategoriesMap::iterator - I = M.ChainedObjCCategories.find(InterfaceID); - if (I == M.ChainedObjCCategories.end()) + bool operator()(const LocalRedeclarationsInfo &X, + const LocalRedeclarationsInfo &Y) { + return X.FirstID < Y.FirstID; + } + bool operator()(DeclID X, DeclID Y) { + return X < Y; + } + }; + + /// \brief Module visitor class that finds all of the redeclarations of a + /// + class RedeclChainVisitor { + ASTReader &Reader; + SmallVectorImpl<DeclID> &SearchDecls; + llvm::SmallPtrSet<Decl *, 16> &Deserialized; + GlobalDeclID CanonID; + llvm::SmallVector<Decl *, 4> Chain; + + public: + RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls, + llvm::SmallPtrSet<Decl *, 16> &Deserialized, + GlobalDeclID CanonID) + : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized), + CanonID(CanonID) { + for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) + addToChain(Reader.GetDecl(SearchDecls[I])); + } + + static bool visit(ModuleFile &M, bool Preorder, void *UserData) { + if (Preorder) return false; - - ObjCCategoryDecl * - HeadCat = Reader.GetLocalDeclAs<ObjCCategoryDecl>(M, I->second.first); - ObjCCategoryDecl * - TailCat = Reader.GetLocalDeclAs<ObjCCategoryDecl>(M, I->second.second); - - addCategories(HeadCat, TailCat); - return false; + + return static_cast<RedeclChainVisitor *>(UserData)->visit(M); } - - void addCategories(ObjCCategoryDecl *HeadCat, - ObjCCategoryDecl *TailCat = 0) { - if (!HeadCat) { - assert(!TailCat); + + void addToChain(Decl *D) { + if (!D) return; + + if (Deserialized.count(D)) { + Deserialized.erase(D); + Chain.push_back(D); } - - if (!TailCat) { - TailCat = HeadCat; - while (TailCat->getNextClassCategory()) - TailCat = TailCat->getNextClassCategory(); + } + + void searchForID(ModuleFile &M, GlobalDeclID GlobalID) { + // Map global ID of the first declaration down to the local ID + // used in this module file. + DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID); + if (!ID) + return; + + // Perform a binary search to find the local redeclarations for this + // declaration (if any). + const LocalRedeclarationsInfo *Result + = std::lower_bound(M.RedeclarationsMap, + M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, + ID, CompareLocalRedeclarationsInfoToID()); + if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap || + Result->FirstID != ID) { + // If we have a previously-canonical singleton declaration that was + // merged into another redeclaration chain, create a trivial chain + // for this single declaration so that it will get wired into the + // complete redeclaration chain. + if (GlobalID != CanonID && + GlobalID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && + GlobalID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls) { + addToChain(Reader.GetDecl(GlobalID)); + } + + return; } + + // Dig out all of the redeclarations. + unsigned Offset = Result->Offset; + unsigned N = M.RedeclarationChains[Offset]; + M.RedeclarationChains[Offset++] = 0; // Don't try to deserialize again + for (unsigned I = 0; I != N; ++I) + addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++])); + } + + bool visit(ModuleFile &M) { + // Visit each of the declarations. + for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) + searchForID(M, SearchDecls[I]); + return false; + } + + ArrayRef<Decl *> getChain() const { + return Chain; + } + }; +} - if (!GlobHeadCat) { - GlobHeadCat = HeadCat; - GlobTailCat = TailCat; - } else { - ASTDeclReader::setNextObjCCategory(GlobTailCat, HeadCat); - GlobTailCat = TailCat; - } +void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { + Decl *D = GetDecl(ID); + Decl *CanonDecl = D->getCanonicalDecl(); + + // Determine the set of declaration IDs we'll be searching for. + llvm::SmallVector<DeclID, 1> SearchDecls; + GlobalDeclID CanonID = 0; + if (D == CanonDecl) { + SearchDecls.push_back(ID); // Always first. + CanonID = ID; + } + MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID); + if (MergedPos != MergedDecls.end()) + SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end()); + + // Build up the list of redeclarations. + RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID); + ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor); + + // Retrieve the chains. + ArrayRef<Decl *> Chain = Visitor.getChain(); + if (Chain.empty()) + return; + + // Hook up the chains. + Decl *MostRecent = CanonDecl->getMostRecentDecl(); + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + if (Chain[I] == CanonDecl) + continue; + + ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent); + MostRecent = Chain[I]; + } + + ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent); +} - llvm::DenseSet<DeclarationName> Checked; - for (ObjCCategoryDecl *Cat = HeadCat, - *CatEnd = TailCat->getNextClassCategory(); - Cat != CatEnd; Cat = Cat->getNextClassCategory()) { - if (Checked.count(Cat->getDeclName())) - continue; - Checked.insert(Cat->getDeclName()); - checkForDuplicate(Cat); - } +namespace { + struct CompareObjCCategoriesInfo { + bool operator()(const ObjCCategoriesInfo &X, DeclID Y) { + return X.DefinitionID < Y; } + + bool operator()(DeclID X, const ObjCCategoriesInfo &Y) { + return X < Y.DefinitionID; + } + + bool operator()(const ObjCCategoriesInfo &X, + const ObjCCategoriesInfo &Y) { + return X.DefinitionID < Y.DefinitionID; + } + bool operator()(DeclID X, DeclID Y) { + return X < Y; + } + }; - /// \brief Warns for duplicate categories that come from different modules. - void checkForDuplicate(ObjCCategoryDecl *Cat) { - DeclarationName Name = Cat->getDeclName(); - // Find the top category with the same name. We do not want to warn for - // duplicates along the established chain because there were already - // warnings for them when the module was created. We only want to warn for - // duplicates between non-dependent modules: - // - // MT // - // / \ // - // ML MR // - // - // We want to warn for duplicates between ML and MR,not between ML and MT. - // - // FIXME: We should not warn for duplicates in diamond: - // - // MT // - // / \ // - // ML MR // - // \ / // - // MB // - // - // If there are duplicates in ML/MR, there will be warning when creating - // MB *and* when importing MB. We should not warn when importing. - for (ObjCCategoryDecl *Next = Cat->getNextClassCategory(); Next; - Next = Next->getNextClassCategory()) { - if (Next->getDeclName() == Name) - Cat = Next; + /// \brief Given an ObjC interface, goes through the modules and links to the + /// interface all the categories for it. + class ObjCCategoriesVisitor { + ASTReader &Reader; + serialization::GlobalDeclID InterfaceID; + ObjCInterfaceDecl *Interface; + llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized; + unsigned PreviousGeneration; + ObjCCategoryDecl *Tail; + llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; + + void add(ObjCCategoryDecl *Cat) { + // Only process each category once. + if (!Deserialized.count(Cat)) + return; + Deserialized.erase(Cat); + + // Check for duplicate categories. + if (Cat->getDeclName()) { + ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()]; + if (Existing && + Reader.getOwningModuleFile(Existing) + != Reader.getOwningModuleFile(Cat)) { + // FIXME: We should not warn for duplicates in diamond: + // + // MT // + // / \ // + // ML MR // + // \ / // + // MB // + // + // If there are duplicates in ML/MR, there will be warning when + // creating MB *and* when importing MB. We should not warn when + // importing. + Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) + << Interface->getDeclName() << Cat->getDeclName(); + Reader.Diag(Existing->getLocation(), diag::note_previous_definition); + } else if (!Existing) { + // Record this category. + Existing = Cat; + } + } + + // Add this category to the end of the chain. + if (Tail) + ASTDeclReader::setNextObjCCategory(Tail, Cat); + else + Interface->setCategoryList(Cat); + Tail = Cat; + } + + public: + ObjCCategoriesVisitor(ASTReader &Reader, + serialization::GlobalDeclID InterfaceID, + ObjCInterfaceDecl *Interface, + llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized, + unsigned PreviousGeneration) + : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface), + Deserialized(Deserialized), PreviousGeneration(PreviousGeneration), + Tail(0) + { + // Populate the name -> category map with the set of known categories. + for (ObjCCategoryDecl *Cat = Interface->getCategoryList(); Cat; + Cat = Cat->getNextClassCategory()) { + if (Cat->getDeclName()) + NameCategoryMap[Cat->getDeclName()] = Cat; + + // Keep track of the tail of the category list. + Tail = Cat; } + } - ObjCCategoryDecl *&PrevCat = NameCategoryMap[Name]; - if (!PrevCat) - PrevCat = Cat; + static bool visit(ModuleFile &M, void *UserData) { + return static_cast<ObjCCategoriesVisitor *>(UserData)->visit(M); + } - if (PrevCat != Cat) { - Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) - << Interface->getDeclName() << Name; - Reader.Diag(PrevCat->getLocation(), diag::note_previous_definition); + bool visit(ModuleFile &M) { + // If we've loaded all of the category information we care about from + // this module file, we're done. + if (M.Generation <= PreviousGeneration) + return true; + + // Map global ID of the definition down to the local ID used in this + // module file. If there is no such mapping, we'll find nothing here + // (or in any module it imports). + DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID); + if (!LocalID) + return true; + + // Perform a binary search to find the local redeclarations for this + // declaration (if any). + const ObjCCategoriesInfo *Result + = std::lower_bound(M.ObjCCategoriesMap, + M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap, + LocalID, CompareObjCCategoriesInfo()); + if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap || + Result->DefinitionID != LocalID) { + // We didn't find anything. If the class definition is in this module + // file, then the module files it depends on cannot have any categories, + // so suppress further lookup. + return Reader.isDeclIDFromModule(InterfaceID, M); } + + // We found something. Dig out all of the categories. + unsigned Offset = Result->Offset; + unsigned N = M.ObjCCategories[Offset]; + M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again + for (unsigned I = 0; I != N; ++I) + add(cast_or_null<ObjCCategoryDecl>( + Reader.GetLocalDecl(M, M.ObjCCategories[Offset++]))); + return true; } - - ObjCCategoryDecl *getHeadCategory() const { return GlobHeadCat; } }; } -void ASTReader::loadObjCChainedCategories(serialization::GlobalDeclID ID, - ObjCInterfaceDecl *D) { - ObjCChainedCategoriesVisitor Visitor(*this, ID, D); - ModuleMgr.visit(ObjCChainedCategoriesVisitor::visit, &Visitor); - // Also add the categories that the interface already links to. - Visitor.addCategories(D->getCategoryList()); - D->setCategoryList(Visitor.getHeadCategory()); +void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, + ObjCInterfaceDecl *D, + unsigned PreviousGeneration) { + ObjCCategoriesVisitor Visitor(*this, ID, D, CategoriesDeserialized, + PreviousGeneration); + ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor); } -void ASTDeclReader::UpdateDecl(Decl *D, Module &Module, +void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, const RecordData &Record) { unsigned Idx = 0; while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { - case UPD_CXX_SET_DEFINITIONDATA: { - CXXRecordDecl *RD = cast<CXXRecordDecl>(D); - CXXRecordDecl *DefinitionDecl - = Reader.ReadDeclAs<CXXRecordDecl>(Module, Record, Idx); - assert(!RD->DefinitionData && "DefinitionData is already set!"); - InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx); - break; - } - case UPD_CXX_ADDED_IMPLICIT_MEMBER: - cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(Module, Record, Idx)); + cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx)); break; case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: // It will be added to the template's specializations set when loaded. - (void)Reader.ReadDecl(Module, Record, Idx); + (void)Reader.ReadDecl(ModuleFile, Record, Idx); break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { NamespaceDecl *Anon - = Reader.ReadDeclAs<NamespaceDecl>(Module, Record, Idx); - // Guard against these being loaded out of original order. Don't use - // getNextNamespace(), since it tries to access the context and can't in - // the middle of deserialization. - if (!Anon->NextNamespace) { + = Reader.ReadDeclAs<NamespaceDecl>(ModuleFile, Record, Idx); + + // Each module has its own anonymous namespace, which is disjoint from + // any other module's anonymous namespaces, so don't attach the anonymous + // namespace at all. + if (ModuleFile.Kind != MK_Module) { if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) TU->setAnonymousNamespace(Anon); else - cast<NamespaceDecl>(D)->OrigOrAnonNamespace.setPointer(Anon); + cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon); } break; } case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation( - Reader.ReadSourceLocation(Module, Record, Idx)); + Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; } } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h index 99e8be5..3a1dfcf 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h @@ -15,6 +15,7 @@ #include "clang/Basic/OnDiskHashTable.h" #include "clang/AST/DeclarationName.h" +#include "llvm/Support/Endian.h" #include <utility> #include <sys/stat.h> @@ -26,7 +27,7 @@ struct HeaderFileInfo; namespace serialization { -class Module; +class ModuleFile; namespace reader { @@ -34,14 +35,15 @@ namespace reader { /// in an AST file. class ASTDeclContextNameLookupTrait { ASTReader &Reader; - Module &F; + ModuleFile &F; public: /// \brief Pair of begin/end iterators for DeclIDs. /// /// Note that these declaration IDs are local to the module that contains this /// particular lookup t - typedef std::pair<DeclID *, DeclID *> data_type; + typedef llvm::support::ulittle32_t LE32DeclID; + typedef std::pair<LE32DeclID *, LE32DeclID *> data_type; /// \brief Special internal key for declaration names. /// The hash table creates keys for comparison; we do not create @@ -56,7 +58,7 @@ public: typedef DeclNameKey internal_key_type; explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, - Module &F) + ModuleFile &F) : Reader(Reader), F(F) { } static bool EqualKey(const internal_key_type& a, @@ -84,7 +86,7 @@ typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait> /// \brief Class that performs lookup for an identifier stored in an AST file. class ASTIdentifierLookupTrait { ASTReader &Reader; - Module &F; + ModuleFile &F; // If we know the IdentifierInfo in advance, it is here and we will // not build a new one. Used when deserializing information about an @@ -98,7 +100,7 @@ public: typedef external_key_type internal_key_type; - ASTIdentifierLookupTrait(ASTReader &Reader, Module &F, + ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F, IdentifierInfo *II = 0) : Reader(Reader), F(F), KnownII(II) { } @@ -127,6 +129,9 @@ public: IdentifierInfo *ReadData(const internal_key_type& k, const unsigned char* d, unsigned DataLen); + + ASTReader &getReader() const { return Reader; } + }; /// \brief The on-disk hash table used to contain information about @@ -138,7 +143,7 @@ typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait> /// method pool stored in an AST file. class ASTSelectorLookupTrait { ASTReader &Reader; - Module &F; + ModuleFile &F; public: struct data_type { @@ -150,7 +155,7 @@ public: typedef Selector external_key_type; typedef external_key_type internal_key_type; - ASTSelectorLookupTrait(ASTReader &Reader, Module &F) + ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F) : Reader(Reader), F(F) { } static bool EqualKey(const internal_key_type& a, @@ -185,7 +190,7 @@ typedef OnDiskChainedHashTable<ASTSelectorLookupTrait> /// and symlinks. class HeaderFileInfoTrait { ASTReader &Reader; - Module &M; + ModuleFile &M; HeaderSearch *HS; const char *FrameworkStrings; const char *SearchPath; @@ -210,7 +215,7 @@ public: typedef HeaderFileInfo data_type; - HeaderFileInfoTrait(ASTReader &Reader, Module &M, HeaderSearch *HS, + HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS, const char *FrameworkStrings, const char *SearchPath = 0) : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings), diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp index ab07b85..2eeb090 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/StmtVisitor.h" +#include "llvm/ADT/SmallString.h" using namespace clang; using namespace clang::serialization; @@ -25,7 +26,7 @@ namespace clang { typedef ASTReader::RecordData RecordData; ASTReader &Reader; - Module &F; + ModuleFile &F; llvm::BitstreamCursor &DeclsCursor; const ASTReader::RecordData &Record; unsigned &Idx; @@ -66,7 +67,7 @@ namespace clang { } public: - ASTStmtReader(ASTReader &Reader, Module &F, + ASTStmtReader(ASTReader &Reader, ModuleFile &F, llvm::BitstreamCursor &Cursor, const ASTReader::RecordData &Record, unsigned &Idx) : Reader(Reader), F(F), DeclsCursor(Cursor), Record(Record), Idx(Idx) { } @@ -78,7 +79,10 @@ namespace clang { /// \brief The number of record fields required for the Expr class /// itself. static const unsigned NumExprFields = NumStmtFields + 7; - + + /// \brief Read and initialize a ExplicitTemplateArgumentList structure. + void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, + unsigned NumTemplateArgs); /// \brief Read and initialize a ExplicitTemplateArgumentList structure. void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, unsigned NumTemplateArgs); @@ -91,15 +95,16 @@ namespace clang { } void ASTStmtReader:: -ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, - unsigned NumTemplateArgs) { +ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, + unsigned NumTemplateArgs) { + SourceLocation TemplateKWLoc = ReadSourceLocation(Record, Idx); TemplateArgumentListInfo ArgInfo; ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx)); ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx)); for (unsigned i = 0; i != NumTemplateArgs; ++i) ArgInfo.addArgument( Reader.ReadTemplateArgumentLoc(F, Record, Idx)); - ArgList.initializeFrom(ArgInfo); + Args.initializeFrom(TemplateKWLoc, ArgInfo); } void ASTStmtReader::VisitStmt(Stmt *S) { @@ -326,10 +331,11 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.HasQualifier = Record[Idx++]; E->DeclRefExprBits.HasFoundDecl = Record[Idx++]; - E->DeclRefExprBits.HasExplicitTemplateArgs = Record[Idx++]; + E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record[Idx++]; E->DeclRefExprBits.HadMultipleCandidates = Record[Idx++]; + E->DeclRefExprBits.RefersToEnclosingLocal = Record[Idx++]; unsigned NumTemplateArgs = 0; - if (E->hasExplicitTemplateArgs()) + if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record[Idx++]; if (E->hasQualifier()) @@ -339,9 +345,9 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { if (E->hasFoundDecl()) E->getInternalFoundDecl() = ReadDeclAs<NamedDecl>(Record, Idx); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - NumTemplateArgs); + if (E->hasTemplateKWAndArgsInfo()) + ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), + NumTemplateArgs); E->setDecl(ReadDeclAs<ValueDecl>(Record, Idx)); E->setLocation(ReadSourceLocation(Record, Idx)); @@ -372,12 +378,13 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { assert(Record[Idx] == E->getNumConcatenated() && "Wrong number of concatenated tokens!"); ++Idx; - E->Kind = static_cast<StringLiteral::StringKind>(Record[Idx++]); - E->IsPascal = Record[Idx++]; + StringLiteral::StringKind kind = + static_cast<StringLiteral::StringKind>(Record[Idx++]); + bool isPascal = Record[Idx++]; // Read string data - llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); - E->setString(Reader.getContext(), Str.str()); + SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); + E->setString(Reader.getContext(), Str.str(), kind, isPascal); Idx += Len; // Read source locations @@ -567,8 +574,6 @@ ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { E->SubExprs[BinaryConditionalOperator::RHS] = Reader.ReadSubExpr(); E->QuestionLoc = ReadSourceLocation(Record, Idx); E->ColonLoc = ReadSourceLocation(Record, Idx); - - E->getOpaqueValue()->setSourceExpr(E->getCommon()); } void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { @@ -614,6 +619,7 @@ void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { } else E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(Record, Idx); E->sawArrayRangeDesignator(Record[Idx++]); + E->setInitializesStdInitializerList(Record[Idx++]); unsigned NumInits = Record[Idx++]; E->reserveInits(Reader.getContext(), NumInits); if (isArrayFiller) { @@ -747,14 +753,6 @@ void ASTStmtReader::VisitBlockExpr(BlockExpr *E) { E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx)); } -void ASTStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - VisitExpr(E); - E->setDecl(ReadDeclAs<VarDecl>(Record, Idx)); - E->setLocation(ReadSourceLocation(Record, Idx)); - E->setByRef(Record[Idx++]); - E->setConstQualAdded(Record[Idx++]); -} - void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); E->NumAssocs = Record[Idx++]; @@ -774,23 +772,30 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { E->RParenLoc = ReadSourceLocation(Record, Idx); } -void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) { +void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) { VisitExpr(E); - E->setOp(AtomicExpr::AtomicOp(Record[Idx++])); - E->setPtr(Reader.ReadSubExpr()); - E->setOrder(Reader.ReadSubExpr()); - E->setNumSubExprs(2); - if (E->getOp() != AtomicExpr::Load) { - E->setVal1(Reader.ReadSubExpr()); - E->setNumSubExprs(3); - } - if (E->isCmpXChg()) { - E->setOrderFail(Reader.ReadSubExpr()); - E->setVal2(Reader.ReadSubExpr()); - E->setNumSubExprs(5); + unsigned numSemanticExprs = Record[Idx++]; + assert(numSemanticExprs + 1 == E->PseudoObjectExprBits.NumSubExprs); + E->PseudoObjectExprBits.ResultIndex = Record[Idx++]; + + // Read the syntactic expression. + E->getSubExprsBuffer()[0] = Reader.ReadSubExpr(); + + // Read all the semantic expressions. + for (unsigned i = 0; i != numSemanticExprs; ++i) { + Expr *subExpr = Reader.ReadSubExpr(); + E->getSubExprsBuffer()[i+1] = subExpr; } - E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); - E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) { + VisitExpr(E); + E->Op = AtomicExpr::AtomicOp(Record[Idx++]); + E->NumSubExprs = AtomicExpr::getNumSubExprs(E->Op); + for (unsigned I = 0; I != E->NumSubExprs; ++I) + E->SubExprs[I] = Reader.ReadSubExpr(); + E->BuiltinLoc = ReadSourceLocation(Record, Idx); + E->RParenLoc = ReadSourceLocation(Record, Idx); } //===----------------------------------------------------------------------===// @@ -802,6 +807,45 @@ void ASTStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) { E->setAtLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitObjCNumericLiteral(ObjCNumericLiteral *E) { + VisitExpr(E); + // could be one of several IntegerLiteral, FloatLiteral, etc. + E->Number = Reader.ReadSubStmt(); + E->ObjCNumericLiteralMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); + E->AtLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + VisitExpr(E); + unsigned NumElements = Record[Idx++]; + assert(NumElements == E->getNumElements() && "Wrong number of elements"); + Expr **Elements = E->getElements(); + for (unsigned I = 0, N = NumElements; I != N; ++I) + Elements[I] = Reader.ReadSubExpr(); + E->ArrayWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); + E->Range = ReadSourceRange(Record, Idx); +} + +void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + VisitExpr(E); + unsigned NumElements = Record[Idx++]; + assert(NumElements == E->getNumElements() && "Wrong number of elements"); + bool HasPackExpansions = Record[Idx++]; + assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch"); + ObjCDictionaryLiteral::KeyValuePair *KeyValues = E->getKeyValues(); + ObjCDictionaryLiteral::ExpansionData *Expansions = E->getExpansionData(); + for (unsigned I = 0; I != NumElements; ++I) { + KeyValues[I].Key = Reader.ReadSubExpr(); + KeyValues[I].Value = Reader.ReadSubExpr(); + if (HasPackExpansions) { + Expansions[I].EllipsisLoc = ReadSourceLocation(Record, Idx); + Expansions[I].NumExpansionsPlusOne = Record[Idx++]; + } + } + E->DictWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); + E->Range = ReadSourceRange(Record, Idx); +} + void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { VisitExpr(E); E->setEncodedTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); @@ -834,13 +878,15 @@ void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { VisitExpr(E); + unsigned MethodRefFlags = Record[Idx++]; bool Implicit = Record[Idx++] != 0; if (Implicit) { ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>(Record, Idx); ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>(Record, Idx); - E->setImplicitProperty(Getter, Setter); + E->setImplicitProperty(Getter, Setter, MethodRefFlags); } else { - E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx)); + E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx), + MethodRefFlags); } E->setLocation(ReadSourceLocation(Record, Idx)); E->setReceiverLocation(ReadSourceLocation(Record, Idx)); @@ -857,6 +903,15 @@ void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { } } +void ASTStmtReader::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { + VisitExpr(E); + E->setRBracket(ReadSourceLocation(Record, Idx)); + E->setBaseExpr(Reader.ReadSubExpr()); + E->setKeyExpr(Reader.ReadSubExpr()); + E->GetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx); + E->SetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +} + void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { VisitExpr(E); assert(Record[Idx] == E->getNumArgs()); @@ -864,6 +919,7 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { unsigned NumStoredSelLocs = Record[Idx++]; E->SelLocsKind = Record[Idx++]; E->setDelegateInitCall(Record[Idx++]); + E->IsImplicit = Record[Idx++]; ObjCMessageExpr::ReceiverKind Kind = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]); switch (Kind) { @@ -958,6 +1014,12 @@ void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { S->setThrowLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { + VisitExpr(E); + E->setValue(Record[Idx++]); + E->setLocation(ReadSourceLocation(Record, Idx)); +} + //===----------------------------------------------------------------------===// // C++ Expressions and Statements //===----------------------------------------------------------------------===// @@ -992,6 +1054,15 @@ void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) { S->setBody(Reader.ReadSubStmt()); } +void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { + VisitStmt(S); + S->KeywordLoc = ReadSourceLocation(Record, Idx); + S->IsIfExists = Record[Idx++]; + S->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + ReadDeclarationNameInfo(S->NameInfo, Record, Idx); + S->SubStmt = Reader.ReadSubStmt(); +} + void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); E->setOperator((OverloadedOperatorKind)Record[Idx++]); @@ -1018,6 +1089,35 @@ void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { E->Type = GetTypeSourceInfo(Record, Idx); } +void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { + VisitExpr(E); + unsigned NumCaptures = Record[Idx++]; + assert(NumCaptures == E->NumCaptures);(void)NumCaptures; + unsigned NumArrayIndexVars = Record[Idx++]; + E->IntroducerRange = ReadSourceRange(Record, Idx); + E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record[Idx++]); + E->ExplicitParams = Record[Idx++]; + E->ExplicitResultType = Record[Idx++]; + E->ClosingBrace = ReadSourceLocation(Record, Idx); + + // Read capture initializers. + for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(), + CEnd = E->capture_init_end(); + C != CEnd; ++C) + *C = Reader.ReadSubExpr(); + + // Read array capture index variables. + if (NumArrayIndexVars > 0) { + unsigned *ArrayIndexStarts = E->getArrayIndexStarts(); + for (unsigned I = 0; I != NumCaptures + 1; ++I) + ArrayIndexStarts[I] = Record[Idx++]; + + VarDecl **ArrayIndexVars = E->getArrayIndexVars(); + for (unsigned I = 0; I != NumArrayIndexVars; ++I) + ArrayIndexVars[I] = ReadDeclAs<VarDecl>(Record, Idx); + } +} + void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { VisitExplicitCastExpr(E); SourceRange R = ReadSourceRange(Record, Idx); @@ -1047,6 +1147,11 @@ void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { E->setRParenLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) { + VisitCallExpr(E); + E->UDSuffixLoc = ReadSourceLocation(Record, Idx); +} + void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { VisitExpr(E); E->setValue(Record[Idx++]); @@ -1108,27 +1213,19 @@ void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { VisitExpr(E); E->GlobalNew = Record[Idx++]; - E->Initializer = Record[Idx++]; - E->UsualArrayDeleteWantsSize = Record[Idx++]; bool isArray = Record[Idx++]; - E->setHadMultipleCandidates(Record[Idx++]); + E->UsualArrayDeleteWantsSize = Record[Idx++]; unsigned NumPlacementArgs = Record[Idx++]; - unsigned NumCtorArgs = Record[Idx++]; + E->StoredInitializationStyle = Record[Idx++]; E->setOperatorNew(ReadDeclAs<FunctionDecl>(Record, Idx)); E->setOperatorDelete(ReadDeclAs<FunctionDecl>(Record, Idx)); - E->setConstructor(ReadDeclAs<CXXConstructorDecl>(Record, Idx)); E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx); - SourceRange TypeIdParens; - TypeIdParens.setBegin(ReadSourceLocation(Record, Idx)); - TypeIdParens.setEnd(ReadSourceLocation(Record, Idx)); - E->TypeIdParens = TypeIdParens; + E->TypeIdParens = ReadSourceRange(Record, Idx); E->StartLoc = ReadSourceLocation(Record, Idx); - E->EndLoc = ReadSourceLocation(Record, Idx); - E->ConstructorLParen = ReadSourceLocation(Record, Idx); - E->ConstructorRParen = ReadSourceLocation(Record, Idx); + E->DirectInitRange = ReadSourceRange(Record, Idx); E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs, - NumCtorArgs); + E->StoredInitializationStyle != 0); // Install all the subexpressions. for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end(); @@ -1167,22 +1264,22 @@ void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) { VisitExpr(E); - unsigned NumTemps = Record[Idx++]; - if (NumTemps) { - E->setNumTemporaries(Reader.getContext(), NumTemps); - for (unsigned i = 0; i != NumTemps; ++i) - E->setTemporary(i, Reader.ReadCXXTemporary(F, Record, Idx)); - } - E->setSubExpr(Reader.ReadSubExpr()); + + unsigned NumObjects = Record[Idx++]; + assert(NumObjects == E->getNumObjects()); + for (unsigned i = 0; i != NumObjects; ++i) + E->getObjectsBuffer()[i] = ReadDeclAs<BlockDecl>(Record, Idx); + + E->SubExpr = Reader.ReadSubExpr(); } void ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ VisitExpr(E); - - if (Record[Idx++]) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - Record[Idx++]); + + if (Record[Idx++]) // HasTemplateKWAndArgsInfo + ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), + /*NumTemplateArgs=*/Record[Idx++]); E->Base = Reader.ReadSubExpr(); E->BaseType = Reader.readType(F, Record, Idx); @@ -1196,10 +1293,10 @@ ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ void ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { VisitExpr(E); - - if (Record[Idx++]) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - Record[Idx++]); + + if (Record[Idx++]) // HasTemplateKWAndArgsInfo + ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), + /*NumTemplateArgs=*/Record[Idx++]); E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameInfo(E->NameInfo, Record, Idx); @@ -1219,11 +1316,10 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); - - // Read the explicit template argument list, if available. - if (Record[Idx++]) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - Record[Idx++]); + + if (Record[Idx++]) // HasTemplateKWAndArgsInfo + ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), + /*NumTemplateArgs=*/Record[Idx++]); unsigned NumDecls = Record[Idx++]; UnresolvedSet<8> Decls; @@ -1277,6 +1373,17 @@ void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { E->RhsType = GetTypeSourceInfo(Record, Idx); } +void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { + VisitExpr(E); + E->TypeTraitExprBits.NumArgs = Record[Idx++]; + E->TypeTraitExprBits.Kind = Record[Idx++]; + E->TypeTraitExprBits.Value = Record[Idx++]; + + TypeSourceInfo **Args = E->getTypeSourceInfos(); + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) + Args[I] = GetTypeSourceInfo(Record, Idx); +} + void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { VisitExpr(E); E->ATT = (ArrayTypeTrait)Record[Idx++]; @@ -1348,7 +1455,7 @@ void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); - Idx++; // skip ID + E->SourceExpr = Reader.ReadSubExpr(); E->Loc = ReadSourceLocation(Record, Idx); } @@ -1412,7 +1519,7 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { // ASTReader Implementation //===----------------------------------------------------------------------===// -Stmt *ASTReader::ReadStmt(Module &F) { +Stmt *ASTReader::ReadStmt(ModuleFile &F) { switch (ReadingKind) { case Read_Decl: case Read_Type: @@ -1422,10 +1529,9 @@ Stmt *ASTReader::ReadStmt(Module &F) { } llvm_unreachable("ReadingKind not set ?"); - return 0; } -Expr *ASTReader::ReadExpr(Module &F) { +Expr *ASTReader::ReadExpr(ModuleFile &F) { return cast_or_null<Expr>(ReadStmt(F)); } @@ -1440,10 +1546,14 @@ Expr *ASTReader::ReadSubExpr() { // the stack, with expressions having operands removing those operands from the // stack. Evaluation terminates when we see a STMT_STOP record, and // the single remaining expression on the stack is our result. -Stmt *ASTReader::ReadStmtFromStream(Module &F) { +Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { ReadingKindTracker ReadingKind(Read_Stmt, *this); llvm::BitstreamCursor &Cursor = F.DeclsCursor; + + // Map of offset to previously deserialized stmt. The offset points + /// just after the stmt record. + llvm::DenseMap<uint64_t, Stmt *> StmtEntries; #ifndef NDEBUG unsigned PrevNumStmts = StmtStack.size(); @@ -1483,11 +1593,19 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { Idx = 0; Record.clear(); bool Finished = false; + bool IsStmtReference = false; switch ((StmtCode)Cursor.ReadRecord(Code, Record)) { case STMT_STOP: Finished = true; break; + case STMT_REF_PTR: + IsStmtReference = true; + assert(StmtEntries.find(Record[0]) != StmtEntries.end() && + "No stmt was recorded for this offset reference!"); + S = StmtEntries[Record[Idx++]]; + break; + case STMT_NULL_PTR: S = 0; break; @@ -1569,9 +1687,9 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { Context, /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? - Record[ASTStmtReader::NumExprFields + 4] : 0); + Record[ASTStmtReader::NumExprFields + 5] : 0); break; case EXPR_INTEGER_LITERAL: @@ -1636,9 +1754,11 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); } + SourceLocation TemplateKWLoc; TemplateArgumentListInfo ArgInfo; - bool HasExplicitTemplateArgs = Record[Idx++]; - if (HasExplicitTemplateArgs) { + bool HasTemplateKWAndArgsInfo = Record[Idx++]; + if (HasTemplateKWAndArgsInfo) { + TemplateKWLoc = ReadSourceLocation(F, Record, Idx); unsigned NumTemplateArgs = Record[Idx++]; ArgInfo.setLAngleLoc(ReadSourceLocation(F, Record, Idx)); ArgInfo.setRAngleLoc(ReadSourceLocation(F, Record, Idx)); @@ -1662,8 +1782,9 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { bool IsArrow = Record[Idx++]; S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc, - MemberD, FoundDecl, MemberNameInfo, - HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK); + TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, + HasTemplateKWAndArgsInfo ? &ArgInfo : 0, + T, VK, OK); ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc, MemberD->getDeclName(), Record, Idx); if (HadMultipleCandidates) @@ -1747,10 +1868,6 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { S = new (Context) BlockExpr(Empty); break; - case EXPR_BLOCK_DECL_REF: - S = new (Context) BlockDeclRefExpr(Empty); - break; - case EXPR_GENERIC_SELECTION: S = new (Context) GenericSelectionExpr(Empty); break; @@ -1758,6 +1875,18 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { case EXPR_OBJC_STRING_LITERAL: S = new (Context) ObjCStringLiteral(Empty); break; + case EXPR_OBJC_NUMERIC_LITERAL: + S = new (Context) ObjCNumericLiteral(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; @@ -1773,9 +1902,11 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { 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"); - break; case EXPR_OBJC_MESSAGE_EXPR: S = ObjCMessageExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields], @@ -1813,6 +1944,9 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { case STMT_OBJC_AUTORELEASE_POOL: S = new (Context) ObjCAutoreleasePoolStmt(Empty); break; + case EXPR_OBJC_BOOL_LITERAL: + S = new (Context) ObjCBoolLiteralExpr(Empty); + break; case STMT_SEH_EXCEPT: S = new (Context) SEHExceptStmt(Empty); break; @@ -1835,6 +1969,13 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { S = new (Context) CXXForRangeStmt(Empty); break; + case STMT_MS_DEPENDENT_EXISTS: + S = new (Context) MSDependentExistsStmt(SourceLocation(), true, + NestedNameSpecifierLoc(), + DeclarationNameInfo(), + 0); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; @@ -1875,6 +2016,10 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; + case EXPR_USER_DEFINED_LITERAL: + S = new (Context) UserDefinedLiteral(Context, Empty); + break; + case EXPR_CXX_BOOL_LITERAL: S = new (Context) CXXBoolLiteralExpr(Empty); break; @@ -1927,12 +2072,13 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { break; case EXPR_EXPR_WITH_CLEANUPS: - S = new (Context) ExprWithCleanups(Empty); + S = ExprWithCleanups::Create(Context, Empty, + Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: S = CXXDependentScopeMemberExpr::CreateEmpty(Context, - /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] : 0); @@ -1940,7 +2086,7 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: S = DependentScopeDeclRefExpr::CreateEmpty(Context, - /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] : 0); @@ -1953,7 +2099,7 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { case EXPR_CXX_UNRESOLVED_MEMBER: S = UnresolvedMemberExpr::CreateEmpty(Context, - /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] : 0); @@ -1961,7 +2107,7 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { case EXPR_CXX_UNRESOLVED_LOOKUP: S = UnresolvedLookupExpr::CreateEmpty(Context, - /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] : 0); @@ -1975,6 +2121,11 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { S = new (Context) BinaryTypeTraitExpr(Empty); break; + case EXPR_TYPE_TRAIT: + S = TypeTraitExpr::CreateDeserialized(Context, + Record[ASTStmtReader::NumExprFields]); + break; + case EXPR_ARRAY_TYPE_TRAIT: S = new (Context) ArrayTypeTraitExpr(Empty); break; @@ -2007,20 +2158,9 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { S = new (Context) MaterializeTemporaryExpr(Empty); break; - case EXPR_OPAQUE_VALUE: { - unsigned key = Record[ASTStmtReader::NumExprFields]; - OpaqueValueExpr *&expr = OpaqueValueExprs[key]; - - // If we already have an entry for this opaque value expression, - // don't bother reading it again. - if (expr) { - StmtStack.push_back(expr); - continue; - } - - S = expr = new (Context) OpaqueValueExpr(Empty); + case EXPR_OPAQUE_VALUE: + S = new (Context) OpaqueValueExpr(Empty); break; - } case EXPR_CUDA_KERNEL_CALL: S = new (Context) CUDAKernelCallExpr(Context, Empty); @@ -2030,9 +2170,23 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { S = new (Context) AsTypeExpr(Empty); break; + case EXPR_PSEUDO_OBJECT: { + unsigned numSemanticExprs = Record[ASTStmtReader::NumExprFields]; + S = PseudoObjectExpr::Create(Context, Empty, numSemanticExprs); + break; + } + case EXPR_ATOMIC: S = new (Context) AtomicExpr(Empty); break; + + case EXPR_LAMBDA: { + unsigned NumCaptures = Record[ASTStmtReader::NumExprFields]; + unsigned NumArrayIndexVars = Record[ASTStmtReader::NumExprFields + 1]; + S = LambdaExpr::CreateDeserialized(Context, NumCaptures, + NumArrayIndexVars); + break; + } } // We hit a STMT_STOP, so we're done with this expression. @@ -2041,8 +2195,11 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { ++NumStatementsRead; - if (S) + if (S && !IsStmtReference) { Reader.Visit(S); + StmtEntries[Cursor.GetCurrentBitNo()] = S; + } + assert(Idx == Record.size() && "Invalid deserialization of statement"); StmtStack.push_back(S); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index a1645d7..a4301b5 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -185,6 +185,7 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I) Writer.AddTypeRef(T->getArgType(I), Record); Record.push_back(T->isVariadic()); + Record.push_back(T->hasTrailingReturn()); Record.push_back(T->getTypeQuals()); Record.push_back(static_cast<unsigned>(T->getRefQualifier())); Record.push_back(T->getExceptionSpecType()); @@ -221,6 +222,7 @@ void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) { } void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) { + Writer.AddTypeRef(T->getUnderlyingType(), Record); Writer.AddStmt(T->getUnderlyingExpr()); Code = TYPE_DECLTYPE; } @@ -239,7 +241,7 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) { void ASTTypeWriter::VisitTagType(const TagType *T) { Record.push_back(T->isDependentType()); - Writer.AddDeclRef(T->getDecl(), Record); + Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record); assert(!T->isBeingDefined() && "Cannot serialize in the middle of a type definition"); } @@ -363,13 +365,13 @@ void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { } void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { - Writer.AddDeclRef(T->getDecl(), Record); + Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record); Writer.AddTypeRef(T->getInjectedSpecializationType(), Record); Code = TYPE_INJECTED_CLASS_NAME; } void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - Writer.AddDeclRef(T->getDecl(), Record); + Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record); Code = TYPE_OBJC_INTERFACE; } @@ -552,6 +554,7 @@ void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc( } void TypeLocWriter::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { + Writer.AddSourceLocation(TL.getTemplateKeywordLoc(), Record); Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record); Writer.AddSourceLocation(TL.getLAngleLoc(), Record); Writer.AddSourceLocation(TL.getRAngleLoc(), Record); @@ -564,22 +567,23 @@ void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { Writer.AddSourceLocation(TL.getRParenLoc(), Record); } void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); + Writer.AddSourceLocation(TL.getElaboratedKeywordLoc(), Record); Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); } void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); + Writer.AddSourceLocation(TL.getElaboratedKeywordLoc(), Record); Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); + Writer.AddSourceLocation(TL.getElaboratedKeywordLoc(), Record); Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); - Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getTemplateKeywordLoc(), Record); + Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record); Writer.AddSourceLocation(TL.getLAngleLoc(), Record); Writer.AddSourceLocation(TL.getRAngleLoc(), Record); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) @@ -689,9 +693,11 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_GNU_NULL); RECORD(EXPR_SHUFFLE_VECTOR); RECORD(EXPR_BLOCK); - RECORD(EXPR_BLOCK_DECL_REF); RECORD(EXPR_GENERIC_SELECTION); RECORD(EXPR_OBJC_STRING_LITERAL); + RECORD(EXPR_OBJC_NUMERIC_LITERAL); + RECORD(EXPR_OBJC_ARRAY_LITERAL); + RECORD(EXPR_OBJC_DICTIONARY_LITERAL); RECORD(EXPR_OBJC_ENCODE); RECORD(EXPR_OBJC_SELECTOR_EXPR); RECORD(EXPR_OBJC_PROTOCOL_EXPR); @@ -705,6 +711,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(STMT_OBJC_AT_TRY); RECORD(STMT_OBJC_AT_SYNCHRONIZED); RECORD(STMT_OBJC_AT_THROW); + RECORD(EXPR_OBJC_BOOL_LITERAL); RECORD(EXPR_CXX_OPERATOR_CALL); RECORD(EXPR_CXX_CONSTRUCT); RECORD(EXPR_CXX_STATIC_CAST); @@ -712,6 +719,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_CXX_REINTERPRET_CAST); RECORD(EXPR_CXX_CONST_CAST); RECORD(EXPR_CXX_FUNCTIONAL_CAST); + RECORD(EXPR_USER_DEFINED_LITERAL); RECORD(EXPR_CXX_BOOL_LITERAL); RECORD(EXPR_CXX_NULL_PTR_LITERAL); RECORD(EXPR_CXX_TYPEID_EXPR); @@ -778,7 +786,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(IMPORTS); RECORD(REFERENCED_SELECTOR_POOL); RECORD(TU_UPDATE_LEXICAL); - RECORD(REDECLS_UPDATE_LATEST); + RECORD(LOCAL_REDECLARATIONS_MAP); RECORD(SEMA_DECL_REFS); RECORD(WEAK_UNDECLARED_IDENTIFIERS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS); @@ -798,7 +806,13 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(KNOWN_NAMESPACES); RECORD(MODULE_OFFSET_MAP); RECORD(SOURCE_MANAGER_LINE_TABLE); - + RECORD(OBJC_CATEGORIES_MAP); + RECORD(FILE_SORTED_DECLS); + RECORD(IMPORTED_MODULES); + RECORD(MERGED_DECLARATIONS); + RECORD(LOCAL_REDECLARATIONS); + RECORD(OBJC_CATEGORIES); + // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); RECORD(SM_SLOC_FILE_ENTRY); @@ -862,8 +876,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_OBJC_PROTOCOL); RECORD(DECL_OBJC_IVAR); RECORD(DECL_OBJC_AT_DEFS_FIELD); - RECORD(DECL_OBJC_CLASS); - RECORD(DECL_OBJC_FORWARD_PROTOCOL); RECORD(DECL_OBJC_CATEGORY); RECORD(DECL_OBJC_CATEGORY_IMPL); RECORD(DECL_OBJC_IMPLEMENTATION); @@ -969,6 +981,7 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Has errors MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); @@ -979,6 +992,7 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, Record.push_back(CLANG_VERSION_MAJOR); Record.push_back(CLANG_VERSION_MINOR); Record.push_back(!isysroot.empty()); + Record.push_back(ASTHasCompilerErrors); const std::string &Triple = Target.getTriple().getTriple(); Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple); @@ -1011,7 +1025,7 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); - llvm::SmallString<128> MainFilePath(MainFile->getName()); + SmallString<128> MainFilePath(MainFile->getName()); llvm::sys::fs::make_absolute(MainFilePath); @@ -1034,7 +1048,7 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); - llvm::SmallString<128> OutputPath(OutputFile); + SmallString<128> OutputPath(OutputFile); llvm::sys::fs::make_absolute(OutputPath); StringRef origDir = llvm::sys::path::parent_path(OutputPath); @@ -1063,6 +1077,9 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ Record.push_back(static_cast<unsigned>(LangOpts.get##Name())); #include "clang/Basic/LangOptions.def" + + Record.push_back(LangOpts.CurrentModule.size()); + Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end()); Stream.EmitRecord(LANGUAGE_OPTIONS, Record); } @@ -1128,7 +1145,7 @@ void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { } // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> StatCacheData; + SmallString<4096> StatCacheData; uint32_t BucketOffset; { llvm::raw_svector_ostream Out(StatCacheData); @@ -1171,7 +1188,10 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { // FileEntry fields. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // BufferOverridden Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name return Stream.EmitAbbrev(Abbrev); } @@ -1218,14 +1238,14 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; - HeaderSearch &HS; + const HeaderSearch &HS; // Keep track of the framework names we've used during serialization. SmallVector<char, 128> FrameworkStringData; llvm::StringMap<unsigned> FrameworkNameOffset; public: - HeaderFileInfoTrait(ASTWriter &Writer, HeaderSearch &HS) + HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS) : Writer(Writer), HS(HS) { } typedef const char *key_type; @@ -1304,7 +1324,7 @@ namespace { /// \param HS The header search structure to save. /// /// \param Chain Whether we're creating a chained AST file. -void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, StringRef isysroot) { +void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); @@ -1320,7 +1340,9 @@ void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, StringRef isysroot) { if (!File) continue; - const HeaderFileInfo &HFI = HS.header_file_begin()[UID]; + // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo + // from the external source if it was not provided already. + const HeaderFileInfo &HFI = HS.getFileInfo(File); if (HFI.External && Chain) continue; @@ -1340,7 +1362,7 @@ void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, StringRef isysroot) { } // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> TableData; + SmallString<4096> TableData; uint32_t BucketOffset; { llvm::raw_svector_ostream Out(TableData); @@ -1414,7 +1436,8 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Figure out which record code to use. unsigned Code; if (SLoc->isFile()) { - if (SLoc->getFile().getContentCache()->OrigEntry) { + const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); + if (Cache->OrigEntry) { Code = SM_SLOC_FILE_ENTRY; SLocFileEntryOffsets.push_back(Stream.GetCurrentBitNo()); } else @@ -1435,7 +1458,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, const SrcMgr::ContentCache *Content = File.getContentCache(); if (Content->OrigEntry) { assert(Content->OrigEntry == Content->ContentsEntry && - "Writing to AST an overriden file is not supported"); + "Writing to AST an overridden file is not supported"); // The source location entry is a file. The blob associated // with this entry is the file name. @@ -1443,12 +1466,21 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Emit size/modification time for this file. Record.push_back(Content->OrigEntry->getSize()); Record.push_back(Content->OrigEntry->getModificationTime()); - + Record.push_back(Content->BufferOverridden); Record.push_back(File.NumCreatedFIDs); - + + FileDeclIDsTy::iterator FDI = FileDeclIDs.find(SLoc); + if (FDI != FileDeclIDs.end()) { + Record.push_back(FDI->second->FirstDeclIndex); + Record.push_back(FDI->second->DeclIDs.size()); + } else { + Record.push_back(0); + Record.push_back(0); + } + // Turn the file name into an absolute path, if it isn't already. const char *Filename = Content->OrigEntry->getName(); - llvm::SmallString<128> FilePath(Filename); + SmallString<128> FilePath(Filename); // Ask the file manager to fixup the relative path for us. This will // honor the working directory. @@ -1461,6 +1493,16 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename); + + if (Content->BufferOverridden) { + Record.clear(); + Record.push_back(SM_SLOC_BUFFER_BLOB); + const llvm::MemoryBuffer *Buffer + = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); + Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, + StringRef(Buffer->getBufferStart(), + Buffer->getBufferSize() + 1)); + } } else { // The source location entry is a buffer. The blob associated // with this entry contains the contents of the buffer. @@ -1629,8 +1671,9 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), E = PP.macro_end(Chain == 0); I != E; ++I) { - if (!IsModule || I->second->isExported()) { - MacroDefinitionsSeen.insert(I->first); + const IdentifierInfo *Name = I->first; + if (!IsModule || I->second->isPublic()) { + MacroDefinitionsSeen.insert(Name); MacrosToEmit.push_back(std::make_pair(I->first, I->second)); } } @@ -1664,15 +1707,17 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // chained PCH, by storing the offset into the original PCH rather than // writing the macro definition a second time. if (MI->isBuiltinMacro() || - (Chain && Name->isFromAST() && MI->isFromAST() && - !MI->hasChangedAfterLoad())) + (Chain && + Name->isFromAST() && !Name->hasChangedSinceDeserialization() && + MI->isFromAST() && !MI->hasChangedAfterLoad())) continue; AddIdentifierRef(Name, Record); MacroOffsets[Name] = Stream.GetCurrentBitNo(); Record.push_back(MI->getDefinitionLoc().getRawEncoding()); Record.push_back(MI->isUsed()); - AddSourceLocation(MI->getExportLocation(), Record); + Record.push_back(MI->isPublic()); + AddSourceLocation(MI->getVisibilityLocation(), Record); unsigned Code; if (MI->isObjectLike()) { Code = PP_MACRO_OBJECT_LIKE; @@ -1784,9 +1829,12 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Record.push_back(ID->getFileName().size()); Record.push_back(ID->wasInQuotes()); Record.push_back(static_cast<unsigned>(ID->getKind())); - llvm::SmallString<64> Buffer; + SmallString<64> Buffer; Buffer += ID->getFileName(); - Buffer += ID->getFile()->getName(); + // Check that the FileEntry is not null because it was not resolved and + // we create a PCH even with compiler errors. + if (ID->getFile()) + Buffer += ID->getFile()->getName(); Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); continue; } @@ -1815,6 +1863,202 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { } } +unsigned ASTWriter::getSubmoduleID(Module *Mod) { + llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod); + if (Known != SubmoduleIDs.end()) + return Known->second; + + return SubmoduleIDs[Mod] = NextSubmoduleID++; +} + +/// \brief Compute the number of modules within the given tree (including the +/// given module). +static unsigned getNumberOfModules(Module *Mod) { + unsigned ChildModules = 0; + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) + ChildModules += getNumberOfModules(*Sub); + + return ChildModules + 1; +} + +void ASTWriter::WriteSubmodules(Module *WritingModule) { + // Determine the dependencies of our module and each of it's submodules. + // FIXME: This feels like it belongs somewhere else, but there are no + // other consumers of this information. + SourceManager &SrcMgr = PP->getSourceManager(); + ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); + for (ASTContext::import_iterator I = Context->local_import_begin(), + IEnd = Context->local_import_end(); + I != IEnd; ++I) { + if (Module *ImportedFrom + = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(), + SrcMgr))) { + ImportedFrom->Imports.push_back(I->getImportedModule()); + } + } + + // Enter the submodule description block. + Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); + + // Write the abbreviations needed for the submodules block. + using namespace llvm; + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules... + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned UmbrellaAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned HeaderAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature + unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev); + + // Write the submodule metadata block. + RecordData Record; + Record.push_back(getNumberOfModules(WritingModule)); + Record.push_back(FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS); + Stream.EmitRecord(SUBMODULE_METADATA, Record); + + // Write all of the submodules. + std::queue<Module *> Q; + Q.push(WritingModule); + while (!Q.empty()) { + Module *Mod = Q.front(); + Q.pop(); + unsigned ID = getSubmoduleID(Mod); + + // Emit the definition of the block. + Record.clear(); + Record.push_back(SUBMODULE_DEFINITION); + Record.push_back(ID); + if (Mod->Parent) { + assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?"); + Record.push_back(SubmoduleIDs[Mod->Parent]); + } else { + Record.push_back(0); + } + Record.push_back(Mod->IsFramework); + Record.push_back(Mod->IsExplicit); + Record.push_back(Mod->IsSystem); + Record.push_back(Mod->InferSubmodules); + Record.push_back(Mod->InferExplicitSubmodules); + Record.push_back(Mod->InferExportWildcard); + Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); + + // Emit the requirements. + for (unsigned I = 0, N = Mod->Requires.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_REQUIRES); + Stream.EmitRecordWithBlob(RequiresAbbrev, Record, + Mod->Requires[I].data(), + Mod->Requires[I].size()); + } + + // Emit the umbrella header, if there is one. + if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) { + Record.clear(); + Record.push_back(SUBMODULE_UMBRELLA_HEADER); + Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, + UmbrellaHeader->getName()); + } else if (const DirectoryEntry *UmbrellaDir = Mod->getUmbrellaDir()) { + Record.clear(); + Record.push_back(SUBMODULE_UMBRELLA_DIR); + Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, + UmbrellaDir->getName()); + } + + // Emit the headers. + for (unsigned I = 0, N = Mod->Headers.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_HEADER); + Stream.EmitRecordWithBlob(HeaderAbbrev, Record, + Mod->Headers[I]->getName()); + } + + // Emit the imports. + if (!Mod->Imports.empty()) { + Record.clear(); + for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) { + unsigned ImportedID = getSubmoduleID(Mod->Imports[I]); + assert(ImportedID && "Unknown submodule!"); + Record.push_back(ImportedID); + } + Stream.EmitRecord(SUBMODULE_IMPORTS, Record); + } + + // Emit the exports. + if (!Mod->Exports.empty()) { + Record.clear(); + for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) { + if (Module *Exported = Mod->Exports[I].getPointer()) { + unsigned ExportedID = SubmoduleIDs[Exported]; + assert(ExportedID > 0 && "Unknown submodule ID?"); + Record.push_back(ExportedID); + } else { + Record.push_back(0); + } + + Record.push_back(Mod->Exports[I].getInt()); + } + Stream.EmitRecord(SUBMODULE_EXPORTS, Record); + } + + // Queue up the submodules of this module. + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) + Q.push(*Sub); + } + + Stream.ExitBlock(); + + assert((NextSubmoduleID - FirstSubmoduleID + == getNumberOfModules(WritingModule)) && "Wrong # of submodules"); +} + +serialization::SubmoduleID +ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) { + if (Loc.isInvalid() || !WritingModule) + return 0; // No submodule + + // Find the module that owns this location. + ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); + Module *OwningMod + = ModMap.inferModuleFromLocation(FullSourceLoc(Loc,PP->getSourceManager())); + if (!OwningMod) + return 0; + + // Check whether this submodule is part of our own module. + if (WritingModule != OwningMod && !OwningMod->isSubModuleOf(WritingModule)) + return 0; + + return getSubmoduleID(OwningMod); +} + void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag) { RecordData Record; for (DiagnosticsEngine::DiagStatePointsTy::const_iterator @@ -1970,6 +2214,29 @@ void ASTWriter::WriteTypeDeclOffsets() { Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets)); } +void ASTWriter::WriteFileDeclIDsMap() { + using namespace llvm; + RecordData Record; + + // Join the vectors of DeclIDs from all files. + SmallVector<DeclID, 256> FileSortedIDs; + for (FileDeclIDsTy::iterator + FI = FileDeclIDs.begin(), FE = FileDeclIDs.end(); FI != FE; ++FI) { + DeclIDInFileInfo &Info = *FI->second; + Info.FirstDeclIndex = FileSortedIDs.size(); + for (LocDeclIDsTy::iterator + DI = Info.DeclIDs.begin(), DE = Info.DeclIDs.end(); DI != DE; ++DI) + FileSortedIDs.push_back(DI->second); + } + + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); + Record.push_back(FILE_SORTED_DECLS); + Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs)); +} + //===----------------------------------------------------------------------===// // Global Method Pool and Selector Serialization //===----------------------------------------------------------------------===// @@ -2117,7 +2384,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { } // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> MethodPool; + SmallString<4096> MethodPool; uint32_t BucketOffset; { ASTMethodPoolTrait Trait(*this); @@ -2190,6 +2457,7 @@ namespace { class ASTIdentifierTableTrait { ASTWriter &Writer; Preprocessor &PP; + IdentifierResolver &IdResolver; bool IsModule; /// \brief Determines whether this is an "interesting" identifier @@ -2199,6 +2467,7 @@ class ASTIdentifierTableTrait { if (II->isPoisoned() || II->isExtensionToken() || II->getObjCOrBuiltinID() || + II->hasRevertedTokenIDToIdentifier() || II->getFETokenInfo<void>()) return true; @@ -2210,7 +2479,7 @@ class ASTIdentifierTableTrait { return false; if (Macro || (Macro = PP.getMacroInfo(II))) - return !Macro->isBuiltinMacro() && (!IsModule || Macro->isExported()); + return !Macro->isBuiltinMacro() && (!IsModule || Macro->isPublic()); return false; } @@ -2222,24 +2491,26 @@ public: typedef IdentID data_type; typedef data_type data_type_ref; - ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, bool IsModule) - : Writer(Writer), PP(PP), IsModule(IsModule) { } + ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, + IdentifierResolver &IdResolver, bool IsModule) + : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { } static unsigned ComputeHash(const IdentifierInfo* II) { return llvm::HashString(II->getName()); } std::pair<unsigned,unsigned> - EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { + EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 MacroInfo *Macro = 0; if (isInterestingIdentifier(II, Macro)) { DataLen += 2; // 2 bytes for builtin ID, flags if (hasMacroDefinition(II, Macro)) - DataLen += 4; - for (IdentifierResolver::iterator D = IdentifierResolver::begin(II), - DEnd = IdentifierResolver::end(); + DataLen += 8; + + for (IdentifierResolver::iterator D = IdResolver.begin(II), + DEnd = IdResolver.end(); D != DEnd; ++D) DataLen += sizeof(DeclID); } @@ -2271,6 +2542,7 @@ public: uint32_t Bits = 0; bool HasMacroDefinition = hasMacroDefinition(II, Macro); Bits = (uint32_t)II->getObjCOrBuiltinID(); + assert((Bits & 0x7ff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); Bits = (Bits << 1) | unsigned(HasMacroDefinition); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); @@ -2278,20 +2550,22 @@ public: Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); clang::io::Emit16(Out, Bits); - if (HasMacroDefinition) + if (HasMacroDefinition) { clang::io::Emit32(Out, Writer.getMacroOffset(II)); - + clang::io::Emit32(Out, + Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc())); + } + // Emit the declaration IDs in reverse order, because the // IdentifierResolver provides the declarations as they would be // visible (e.g., the function "stat" would come before the struct - // "stat"), but IdentifierResolver::AddDeclToIdentifierChain() - // adds declarations to the end of the list (so we need to see the - // struct "status" before the function "status"). + // "stat"), but the ASTReader adds declarations to the end of the list + // (so we need to see the struct "status" before the function "status"). // Only emit declarations that aren't from a chained PCH, though. - SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), - IdentifierResolver::end()); + SmallVector<Decl *, 16> Decls(IdResolver.begin(II), + IdResolver.end()); for (SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), - DEnd = Decls.rend(); + DEnd = Decls.rend(); D != DEnd; ++D) clang::io::Emit32(Out, Writer.getDeclID(*D)); } @@ -2303,14 +2577,16 @@ public: /// 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, bool IsModule) { +void ASTWriter::WriteIdentifierTable(Preprocessor &PP, + IdentifierResolver &IdResolver, + bool IsModule) { using namespace llvm; // Create and write out the blob that contains the identifier // strings. { OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; - ASTIdentifierTableTrait Trait(*this, PP, IsModule); + ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash @@ -2329,16 +2605,17 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, bool IsModule) { ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); ID != IDEnd; ++ID) { assert(ID->first && "NULL identifier in identifier table"); - if (!Chain || !ID->first->isFromAST()) + if (!Chain || !ID->first->isFromAST() || + ID->first->hasChangedSinceDeserialization()) Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second, Trait); } // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> IdentifierTable; + SmallString<4096> IdentifierTable; uint32_t BucketOffset; { - ASTIdentifierTableTrait Trait(*this, PP, IsModule); + ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 clang::io::Emit32(Out, 0); @@ -2512,20 +2789,16 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, // IdentifierInfo chains, don't bother to build a visible-declarations table. // FIXME: In C++ we need the visible declarations in order to "see" the // friend declarations, is there a way to do this without writing the table ? - if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus) + if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus) return 0; - // Force the DeclContext to build a its name-lookup table. - if (!DC->hasExternalVisibleStorage()) - DC->lookup(DeclarationName()); - // Serialize the contents of the mapping used for lookup. Note that, // although we have two very different code paths, the serialized // representation is the same for both cases: a declaration name, // followed by a size, followed by references to the visible // declarations that have that name. uint64_t Offset = Stream.GetCurrentBitNo(); - StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); + StoredDeclsMap *Map = DC->buildLookup(); if (!Map || Map->empty()) return 0; @@ -2565,7 +2838,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, } // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> LookupTable; + SmallString<4096> LookupTable; uint32_t BucketOffset; { llvm::raw_svector_ostream Out(LookupTable); @@ -2590,7 +2863,8 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &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 -/// (in C++) and for namespaces. +/// (in C++), for namespaces, and for classes with forward-declared unscoped +/// enumeration members (in C++11). void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); if (!Map || Map->empty()) @@ -2611,7 +2885,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { } // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> LookupTable; + SmallString<4096> LookupTable; uint32_t BucketOffset; { llvm::raw_svector_ostream Out(LookupTable); @@ -2637,7 +2911,7 @@ void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) { /// \brief Write an OPENCL_EXTENSIONS block for the given OpenCLOptions. void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { - if (!SemaRef.Context.getLangOptions().OpenCL) + if (!SemaRef.Context.getLangOpts().OpenCL) return; const OpenCLOptions &Opts = SemaRef.getOpenCLOptions(); @@ -2647,6 +2921,143 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } +void ASTWriter::WriteRedeclarations() { + RecordData LocalRedeclChains; + SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap; + + for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) { + Decl *First = Redeclarations[I]; + assert(First->getPreviousDecl() == 0 && "Not the first declaration?"); + + Decl *MostRecent = First->getMostRecentDecl(); + + // If we only have a single declaration, there is no point in storing + // a redeclaration chain. + if (First == MostRecent) + continue; + + unsigned Offset = LocalRedeclChains.size(); + unsigned Size = 0; + LocalRedeclChains.push_back(0); // Placeholder for the size. + + // Collect the set of local redeclarations of this declaration. + for (Decl *Prev = MostRecent; Prev != First; + Prev = Prev->getPreviousDecl()) { + if (!Prev->isFromASTFile()) { + AddDeclRef(Prev, LocalRedeclChains); + ++Size; + } + } + LocalRedeclChains[Offset] = Size; + + // Reverse the set of local redeclarations, so that we store them in + // order (since we found them in reverse order). + std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end()); + + // Add the mapping from the first ID to the set of local declarations. + LocalRedeclarationsInfo Info = { getDeclID(First), Offset }; + LocalRedeclsMap.push_back(Info); + + assert(N == Redeclarations.size() && + "Deserialized a declaration we shouldn't have"); + } + + if (LocalRedeclChains.empty()) + return; + + // Sort the local redeclarations map by the first declaration ID, + // since the reader will be performing binary searches on this information. + llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end()); + + // Emit the local redeclarations map. + using namespace llvm; + llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned AbbrevID = Stream.EmitAbbrev(Abbrev); + + RecordData Record; + Record.push_back(LOCAL_REDECLARATIONS_MAP); + Record.push_back(LocalRedeclsMap.size()); + Stream.EmitRecordWithBlob(AbbrevID, Record, + reinterpret_cast<char*>(LocalRedeclsMap.data()), + LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo)); + + // Emit the redeclaration chains. + Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains); +} + +void ASTWriter::WriteObjCCategories() { + llvm::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 (ObjCCategoryDecl *Cat = Class->getCategoryList(); + Cat; Cat = Cat->getNextClassCategory(), ++Size) { + 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); + } + + // Sort the categories map by the definition ID, since the reader will be + // performing binary searches on this information. + llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end()); + + // Emit the categories map. + using namespace llvm; + llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned AbbrevID = Stream.EmitAbbrev(Abbrev); + + RecordData Record; + Record.push_back(OBJC_CATEGORIES_MAP); + Record.push_back(CategoriesMap.size()); + Stream.EmitRecordWithBlob(AbbrevID, Record, + reinterpret_cast<char*>(CategoriesMap.data()), + CategoriesMap.size() * sizeof(ObjCCategoriesInfo)); + + // Emit the category lists. + Stream.EmitRecord(OBJC_CATEGORIES, Categories); +} + +void ASTWriter::WriteMergedDecls() { + if (!Chain || Chain->MergedDecls.empty()) + return; + + RecordData Record; + for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(), + IEnd = Chain->MergedDecls.end(); + I != IEnd; ++I) { + DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID() + : getDeclID(I->first); + assert(CanonID && "Merged declaration not known?"); + + Record.push_back(CanonID); + Record.push_back(I->second.size()); + Record.append(I->second.begin(), I->second.end()); + } + Stream.EmitRecord(MERGED_DECLARATIONS, Record); +} + //===----------------------------------------------------------------------===// // General Serialization Routines //===----------------------------------------------------------------------===// @@ -2705,10 +3116,13 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { } ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) - : Stream(Stream), Context(0), Chain(0), WritingAST(false), + : Stream(Stream), Context(0), PP(0), Chain(0), WritingModule(0), + WritingAST(false), ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), + NextSubmoduleID(FirstSubmoduleID), FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), @@ -2724,11 +3138,20 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) { } +ASTWriter::~ASTWriter() { + for (FileDeclIDsTy::iterator + I = FileDeclIDs.begin(), E = FileDeclIDs.end(); I != E; ++I) + delete I->second; +} + void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, const std::string &OutputFile, - bool IsModule, StringRef isysroot) { + Module *WritingModule, StringRef isysroot, + bool hasErrors) { WritingAST = true; + ASTHasCompilerErrors = hasErrors; + // Emit the file header. Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'P', 8); @@ -2738,8 +3161,12 @@ void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, WriteBlockInfoBlock(); Context = &SemaRef.Context; - WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, IsModule); + PP = &SemaRef.PP; + this->WritingModule = WritingModule; + WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, WritingModule); Context = 0; + PP = 0; + this->WritingModule = 0; WritingAST = false; } @@ -2755,9 +3182,14 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, StringRef isysroot, - const std::string &OutputFile, bool IsModule) { + const std::string &OutputFile, + Module *WritingModule) { using namespace llvm; + // Make sure that the AST reader knows to finalize itself. + if (Chain) + Chain->finalizeForWriting(); + ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; @@ -2769,6 +3201,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID; if (Context.ObjCClassDecl) DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID; + if (Context.ObjCProtocolClassDecl) + DeclIDs[Context.ObjCProtocolClassDecl] = PREDEF_DECL_OBJC_PROTOCOL_ID; if (Context.Int128Decl) DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID; if (Context.UInt128Decl) @@ -2785,11 +3219,20 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, IdentifierTable &Table = PP.getIdentifierTable(); SmallVector<const char *, 32> BuiltinNames; Context.BuiltinInfo.GetBuiltinNames(BuiltinNames, - Context.getLangOptions().NoBuiltin); + Context.getLangOpts().NoBuiltin); for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) getIdentifierRef(&Table.get(BuiltinNames[I])); } + // If there are any out-of-date identifiers, bring them up to date. + if (ExternalPreprocessorSource *ExtSource = PP.getExternalSource()) { + for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), + IDEnd = PP.getIdentifierTable().end(); + ID != IDEnd; ++ID) + if (ID->second->isOutOfDate()) + ExtSource->updateOutOfDateIdentifier(*ID->second); + } + // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. @@ -2890,52 +3333,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); WriteMetadata(Context, isysroot, OutputFile); - WriteLanguageOptions(Context.getLangOptions()); + WriteLanguageOptions(Context.getLangOpts()); if (StatCalls && isysroot.empty()) WriteStatCache(*StatCalls); - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - - if (Chain) { - // Write the mapping information describing our module dependencies and how - // each of those modules were mapped into our own offset/ID space, so that - // the reader can build the appropriate mapping to its own offset/ID space. - // The map consists solely of a blob with the following format: - // *(module-name-len:i16 module-name:len*i8 - // source-location-offset:i32 - // identifier-id:i32 - // preprocessed-entity-id:i32 - // macro-definition-id:i32 - // selector-id:i32 - // declaration-id:i32 - // c++-base-specifiers-id:i32 - // type-id:i32) - // - llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev); - llvm::SmallString<2048> Buffer; - { - llvm::raw_svector_ostream Out(Buffer); - for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(), - MEnd = Chain->ModuleMgr.end(); - M != MEnd; ++M) { - StringRef FileName = (*M)->FileName; - io::Emit16(Out, FileName.size()); - Out.write(FileName.data(), FileName.size()); - io::Emit32(Out, (*M)->SLocEntryBaseOffset); - io::Emit32(Out, (*M)->BaseIdentifierID); - io::Emit32(Out, (*M)->BasePreprocessedEntityID); - io::Emit32(Out, (*M)->BaseSelectorID); - io::Emit32(Out, (*M)->BaseDeclID); - io::Emit32(Out, (*M)->BaseTypeIndex); - } - } - Record.clear(); - Record.push_back(MODULE_OFFSET_MAP); - Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, - Buffer.data(), Buffer.size()); - } // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. @@ -2946,8 +3346,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, I != E; ++I) { if (!(*I)->isFromASTFile()) NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I))); - else if ((*I)->isChangedSinceDeserialization()) - (void)GetDeclRef(*I); // Make sure it's written, but don't record it. } llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); @@ -2978,15 +3376,12 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, } } - // Resolve any declaration pointers within the declaration updates block and - // chained Objective-C categories block to declaration IDs. + // Resolve any declaration pointers within the declaration updates block. ResolveDeclUpdatesBlocks(); - ResolveChainedObjCCategories(); // Form the record of special types. RecordData SpecialTypes; AddTypeRef(Context.getBuiltinVaListType(), SpecialTypes); - AddTypeRef(Context.ObjCProtoType, SpecialTypes); AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); AddTypeRef(Context.getFILEType(), SpecialTypes); AddTypeRef(Context.getjmp_bufType(), SpecialTypes); @@ -2995,7 +3390,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); AddTypeRef(Context.getucontext_tType(), SpecialTypes); - + // Keep writing types and declarations until all types and // declarations have been written. Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); @@ -3014,11 +3409,57 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, } Stream.ExitBlock(); - WritePreprocessor(PP, IsModule); + WriteFileDeclIDsMap(); + WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); + + if (Chain) { + // Write the mapping information describing our module dependencies and how + // each of those modules were mapped into our own offset/ID space, so that + // the reader can build the appropriate mapping to its own offset/ID space. + // The map consists solely of a blob with the following format: + // *(module-name-len:i16 module-name:len*i8 + // source-location-offset:i32 + // identifier-id:i32 + // preprocessed-entity-id:i32 + // macro-definition-id:i32 + // submodule-id:i32 + // selector-id:i32 + // declaration-id:i32 + // c++-base-specifiers-id:i32 + // type-id:i32) + // + llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev); + SmallString<2048> Buffer; + { + llvm::raw_svector_ostream Out(Buffer); + for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(), + MEnd = Chain->ModuleMgr.end(); + M != MEnd; ++M) { + StringRef FileName = (*M)->FileName; + io::Emit16(Out, FileName.size()); + Out.write(FileName.data(), FileName.size()); + io::Emit32(Out, (*M)->SLocEntryBaseOffset); + io::Emit32(Out, (*M)->BaseIdentifierID); + io::Emit32(Out, (*M)->BasePreprocessedEntityID); + io::Emit32(Out, (*M)->BaseSubmoduleID); + io::Emit32(Out, (*M)->BaseSelectorID); + io::Emit32(Out, (*M)->BaseDeclID); + io::Emit32(Out, (*M)->BaseTypeIndex); + } + } + Record.clear(); + Record.push_back(MODULE_OFFSET_MAP); + Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, + Buffer.data(), Buffer.size()); + } + WritePreprocessor(PP, WritingModule != 0); WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); WriteSelectors(SemaRef); WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP, IsModule); + WriteIdentifierTable(PP, SemaRef.IdResolver, WritingModule != 0); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); @@ -3027,20 +3468,11 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, WriteCXXBaseSpecifiersOffsets(); - Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); + // If we're emitting a module, write out the submodule information. + if (WritingModule) + WriteSubmodules(WritingModule); - /// Build a record containing first declarations from a chained PCH and the - /// most recent declarations in this AST that they point to. - RecordData FirstLatestDeclIDs; - for (FirstLatestDeclMap::iterator I = FirstLatestDecls.begin(), - E = FirstLatestDecls.end(); - I != E; ++I) { - AddDeclRef(I->first, FirstLatestDeclIDs); - AddDeclRef(I->second, FirstLatestDeclIDs); - } - - if (!FirstLatestDeclIDs.empty()) - Stream.EmitRecord(REDECLS_UPDATE_LATEST, FirstLatestDeclIDs); + Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); // Write the record containing external, unnamed definitions. if (!ExternalDefinitions.empty()) @@ -3103,10 +3535,34 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, I != E; ++I) WriteDeclContextVisibleUpdate(*I); + if (!WritingModule) { + // Write the submodules that were imported, if any. + RecordData ImportedModules; + for (ASTContext::import_iterator I = Context.local_import_begin(), + IEnd = Context.local_import_end(); + I != IEnd; ++I) { + assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end()); + ImportedModules.push_back(SubmoduleIDs[I->getImportedModule()]); + } + if (!ImportedModules.empty()) { + // Sort module IDs. + llvm::array_pod_sort(ImportedModules.begin(), ImportedModules.end()); + + // Unique module IDs. + ImportedModules.erase(std::unique(ImportedModules.begin(), + ImportedModules.end()), + ImportedModules.end()); + + Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); + } + } + WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); - WriteChainedObjCCategories(); - + WriteMergedDecls(); + WriteRedeclarations(); + WriteObjCCategories(); + // Some simple statistics Record.clear(); Record.push_back(NumStatements); @@ -3125,13 +3581,12 @@ void ASTWriter::ResolveDeclUpdatesBlocks() { const Decl *D = I->first; UpdateRecord &URec = I->second; - if (DeclsToRewrite.count(D)) + if (isRewritten(D)) continue; // The decl will be written completely unsigned Idx = 0, N = URec.size(); while (Idx < N) { switch ((DeclUpdateKind)URec[Idx++]) { - case UPD_CXX_SET_DEFINITIONDATA: case UPD_CXX_ADDED_IMPLICIT_MEMBER: case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: @@ -3158,7 +3613,7 @@ void ASTWriter::WriteDeclUpdatesBlocks() { const Decl *D = I->first; UpdateRecord &URec = I->second; - if (DeclsToRewrite.count(D)) + if (isRewritten(D)) continue; // The decl will be written completely,no need to store updates. uint64_t Offset = Stream.GetCurrentBitNo(); @@ -3176,45 +3631,15 @@ void ASTWriter::WriteDeclReplacementsBlock() { return; RecordData Record; - for (SmallVector<std::pair<DeclID, uint64_t>, 16>::iterator + for (SmallVector<ReplacedDeclInfo, 16>::iterator I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) { - Record.push_back(I->first); - Record.push_back(I->second); + Record.push_back(I->ID); + Record.push_back(I->Offset); + Record.push_back(I->Loc); } Stream.EmitRecord(DECL_REPLACEMENTS, Record); } -void ASTWriter::ResolveChainedObjCCategories() { - for (SmallVector<ChainedObjCCategoriesData, 16>::iterator - I = LocalChainedObjCCategories.begin(), - E = LocalChainedObjCCategories.end(); I != E; ++I) { - ChainedObjCCategoriesData &Data = *I; - Data.InterfaceID = GetDeclRef(Data.Interface); - Data.TailCategoryID = GetDeclRef(Data.TailCategory); - } - -} - -void ASTWriter::WriteChainedObjCCategories() { - if (LocalChainedObjCCategories.empty()) - return; - - RecordData Record; - for (SmallVector<ChainedObjCCategoriesData, 16>::iterator - I = LocalChainedObjCCategories.begin(), - E = LocalChainedObjCCategories.end(); I != E; ++I) { - ChainedObjCCategoriesData &Data = *I; - serialization::DeclID - HeadCatID = getDeclID(Data.Interface->getCategoryList()); - assert(HeadCatID != 0 && "Category not written ?"); - - Record.push_back(Data.InterfaceID); - Record.push_back(HeadCatID); - Record.push_back(Data.TailCategoryID); - } - Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record); -} - void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) { Record.push_back(Loc.getRawEncoding()); } @@ -3397,6 +3822,12 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { if (D == 0) { 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) { @@ -3404,12 +3835,6 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { // enqueue it in the list of declarations to emit. ID = NextDeclID++; DeclTypesToEmit.push(const_cast<Decl *>(D)); - } else if (ID < FirstDeclID && D->isChangedSinceDeserialization()) { - // We don't add it to the replacement collection here, because we don't - // have the offset yet. - DeclTypesToEmit.push(const_cast<Decl *>(D)); - // Reset the flag, so that we don't add this decl multiple times. - const_cast<Decl *>(D)->setChangedSinceDeserialization(false); } return ID; @@ -3419,10 +3844,65 @@ DeclID ASTWriter::getDeclID(const Decl *D) { if (D == 0) return 0; + // If D comes from an AST file, its declaration ID is already known and + // fixed. + if (D->isFromASTFile()) + return D->getGlobalID(); + assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); return DeclIDs[D]; } +static inline bool compLocDecl(std::pair<unsigned, serialization::DeclID> L, + std::pair<unsigned, serialization::DeclID> R) { + return L.first < R.first; +} + +void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { + assert(ID); + assert(D); + + SourceLocation Loc = D->getLocation(); + if (Loc.isInvalid()) + return; + + // We only keep track of the file-level declarations of each file. + if (!D->getLexicalDeclContext()->isFileContext()) + 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)) + return; + + SourceManager &SM = Context->getSourceManager(); + SourceLocation FileLoc = SM.getFileLoc(Loc); + assert(SM.isLocalSourceLocation(FileLoc)); + FileID FID; + unsigned Offset; + llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); + if (FID.isInvalid()) + return; + const SrcMgr::SLocEntry *Entry = &SM.getSLocEntry(FID); + assert(Entry->isFile()); + + DeclIDInFileInfo *&Info = FileDeclIDs[Entry]; + if (!Info) + Info = new DeclIDInFileInfo(); + + std::pair<unsigned, serialization::DeclID> LocDecl(Offset, ID); + LocDeclIDsTy &Decls = Info->DeclIDs; + + if (Decls.empty() || Decls.back().first <= Offset) { + Decls.push_back(LocDecl); + return; + } + + LocDeclIDsTy::iterator + I = std::upper_bound(Decls.begin(), Decls.end(), LocDecl, compLocDecl); + + Decls.insert(I, LocDecl); +} + void ASTWriter::AddDeclarationName(DeclarationName Name, RecordDataImpl &Record) { // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc. Record.push_back(Name.getNameKind()); @@ -3776,11 +4256,11 @@ void ASTWriter::AddCXXCtorInitializers( if (Init->isBaseInitializer()) { Record.push_back(CTOR_INITIALIZER_BASE); - AddTypeSourceInfo(Init->getBaseClassInfo(), Record); + AddTypeSourceInfo(Init->getTypeSourceInfo(), Record); Record.push_back(Init->isBaseVirtual()); } else if (Init->isDelegatingInitializer()) { Record.push_back(CTOR_INITIALIZER_DELEGATING); - AddDeclRef(Init->getTargetConstructor(), Record); + AddTypeSourceInfo(Init->getTypeSourceInfo(), Record); } else if (Init->isMemberInitializer()){ Record.push_back(CTOR_INITIALIZER_MEMBER); AddDeclRef(Init->getMember(), Record); @@ -3807,6 +4287,7 @@ void ASTWriter::AddCXXCtorInitializers( void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) { assert(D->DefinitionData); struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; + Record.push_back(Data.IsLambda); Record.push_back(Data.UserDeclaredConstructor); Record.push_back(Data.UserDeclaredCopyConstructor); Record.push_back(Data.UserDeclaredMoveConstructor); @@ -3824,13 +4305,21 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.HasProtectedFields); Record.push_back(Data.HasPublicFields); Record.push_back(Data.HasMutableFields); + Record.push_back(Data.HasOnlyCMembers); Record.push_back(Data.HasTrivialDefaultConstructor); Record.push_back(Data.HasConstexprNonCopyMoveConstructor); + Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr); + Record.push_back(Data.DefaultedCopyConstructorIsConstexpr); + Record.push_back(Data.DefaultedMoveConstructorIsConstexpr); + Record.push_back(Data.HasConstexprDefaultConstructor); + Record.push_back(Data.HasConstexprCopyConstructor); + Record.push_back(Data.HasConstexprMoveConstructor); Record.push_back(Data.HasTrivialCopyConstructor); Record.push_back(Data.HasTrivialMoveConstructor); Record.push_back(Data.HasTrivialCopyAssignment); Record.push_back(Data.HasTrivialMoveAssignment); Record.push_back(Data.HasTrivialDestructor); + Record.push_back(Data.HasIrrelevantDestructor); Record.push_back(Data.HasNonLiteralTypeFieldsOrBases); Record.push_back(Data.ComputedVisibleConversions); Record.push_back(Data.UserProvidedDefaultConstructor); @@ -3842,6 +4331,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.DeclaredDestructor); Record.push_back(Data.FailedImplicitMoveConstructor); Record.push_back(Data.FailedImplicitMoveAssignment); + // IsLambda bit is already saved. Record.push_back(Data.NumBases); if (Data.NumBases > 0) @@ -3858,6 +4348,27 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec AddUnresolvedSet(Data.VisibleConversions, Record); // Data.Definition is the owning decl, no need to write it. AddDeclRef(Data.FirstFriend, Record); + + // Add lambda-specific data. + if (Data.IsLambda) { + CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData(); + Record.push_back(Lambda.Dependent); + Record.push_back(Lambda.NumCaptures); + Record.push_back(Lambda.NumExplicitCaptures); + Record.push_back(Lambda.ManglingNumber); + AddDeclRef(Lambda.ContextDecl, Record); + for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { + LambdaExpr::Capture &Capture = Lambda.Captures[I]; + AddSourceLocation(Capture.getLocation(), Record); + Record.push_back(Capture.isImplicit()); + Record.push_back(Capture.getCaptureKind()); // FIXME: stable! + VarDecl *Var = Capture.capturesVariable()? Capture.getCapturedVar() : 0; + AddDeclRef(Var, Record); + AddSourceLocation(Capture.isPackExpansion()? Capture.getEllipsisLoc() + : SourceLocation(), + Record); + } + } } void ASTWriter::ReaderInitialized(ASTReader *Reader) { @@ -3866,6 +4377,7 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && + FirstSubmoduleID == NextSubmoduleID && FirstSelectorID == NextSelectorID && "Setting chain after writing has started."); @@ -3874,11 +4386,13 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); + FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; NextSelectorID = FirstSelectorID; + NextSubmoduleID = FirstSubmoduleID; } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { @@ -3898,10 +4412,6 @@ void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { StoredIdx = Idx; } -void ASTWriter::DeclRead(DeclID ID, const Decl *D) { - DeclIDs[D] = ID; -} - void ASTWriter::SelectorRead(SelectorID ID, Selector S) { SelectorIDs[S] = ID; } @@ -3912,6 +4422,15 @@ void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinitions[MD] = ID; } +void ASTWriter::MacroVisible(IdentifierInfo *II) { + DeserializedMacroNames.push_back(II); +} + +void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { + assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end()); + SubmoduleIDs[Mod] = ID; +} + void ASTWriter::CompletedTagDefinition(const TagDecl *D) { assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); @@ -3923,22 +4442,6 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { // have created a new definition decl instead ? RewriteDecl(RD); } - - for (CXXRecordDecl::redecl_iterator - I = RD->redecls_begin(), E = RD->redecls_end(); I != E; ++I) { - CXXRecordDecl *Redecl = cast<CXXRecordDecl>(*I); - if (Redecl == RD) - continue; - - // We are interested when a PCH decl is modified. - if (Redecl->isFromASTFile()) { - UpdateRecord &Record = DeclUpdates[Redecl]; - Record.push_back(UPD_CXX_SET_DEFINITIONDATA); - assert(Redecl->DefinitionData); - assert(Redecl->DefinitionData->Definition == D); - Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl - } - } } } void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { @@ -4023,11 +4526,23 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, assert(!WritingAST && "Already writing the AST!"); if (!IFD->isFromASTFile()) return; // Declaration not imported from PCH. - if (CatD->getNextClassCategory() && - !CatD->getNextClassCategory()->isFromASTFile()) - return; // We already recorded that the tail of a category chain should be - // attached to an interface. + + assert(IFD->getDefinition() && "Category on a class without a definition?"); + ObjCClassesWithCategories.insert( + const_cast<ObjCInterfaceDecl *>(IFD->getDefinition())); +} + + +void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt) { + const ObjCInterfaceDecl *D = ClassExt->getClassInterface(); + if (!D) + return; + + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; // Declaration not imported from PCH. - ChainedObjCCategoriesData Data = { IFD, CatD, 0, 0 }; - LocalChainedObjCCategories.push_back(Data); + RewriteDecl(D); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp index a8243e5..7a4ef63 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp @@ -12,12 +12,14 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTWriter.h" +#include "clang/Serialization/ASTReader.h" #include "ASTCommon.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/DeclContextInternals.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/Twine.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/ErrorHandling.h" @@ -54,6 +56,7 @@ namespace clang { void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *D); + void VisitTypedefNameDecl(TypedefNameDecl *D); void VisitTypedefDecl(TypedefDecl *D); void VisitTypeAliasDecl(TypeAliasDecl *D); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); @@ -93,6 +96,7 @@ namespace clang { void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); + void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); void VisitFriendDecl(FriendDecl *D); void VisitFriendTemplateDecl(FriendTemplateDecl *D); @@ -111,8 +115,6 @@ namespace clang { void VisitObjCIvarDecl(ObjCIvarDecl *D); void VisitObjCProtocolDecl(ObjCProtocolDecl *D); void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); void VisitObjCCategoryDecl(ObjCCategoryDecl *D); void VisitObjCImplDecl(ObjCImplDecl *D); void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); @@ -146,7 +148,6 @@ void ASTDeclWriter::Visit(Decl *D) { void ASTDeclWriter::VisitDecl(Decl *D) { Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record); Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record); - Writer.AddSourceLocation(D->getLocation(), Record); Record.push_back(D->isInvalidDecl()); Record.push_back(D->hasAttrs()); if (D->hasAttrs()) @@ -154,8 +155,10 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Record.push_back(D->isImplicit()); Record.push_back(D->isUsed(false)); Record.push_back(D->isReferenced()); + Record.push_back(D->isTopLevelDeclInObjCContainer()); Record.push_back(D->getAccess()); - Record.push_back(D->ModulePrivate); + Record.push_back(D->isModulePrivate()); + Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation())); } void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { @@ -173,16 +176,21 @@ void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); } -void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { +void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) { + VisitRedeclarable(D); VisitTypeDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); + Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); +} +void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { + VisitTypedefNameDecl(D); if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - D->RedeclLink.getNext() == D && + D->getFirstDeclaration() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && + !D->isTopLevelDeclInObjCContainer() && D->getAccess() == AS_none && !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier) @@ -192,14 +200,13 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { } void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { - VisitTypeDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); + VisitTypedefNameDecl(D); Code = serialization::DECL_TYPEALIAS; } void ASTDeclWriter::VisitTagDecl(TagDecl *D) { - VisitTypeDecl(D); VisitRedeclarable(D); + VisitTypeDecl(D); Record.push_back(D->getIdentifierNamespace()); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding Record.push_back(D->isCompleteDefinition()); @@ -224,15 +231,22 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { Record.push_back(D->isScoped()); Record.push_back(D->isScopedUsingClassTag()); Record.push_back(D->isFixed()); - Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record); + if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { + Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record); + Record.push_back(MemberInfo->getTemplateSpecializationKind()); + Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record); + } else { + Writer.AddDeclRef(0, Record); + } if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - D->RedeclLink.getNext() == D && + D->getFirstDeclaration() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && + !D->isTopLevelDeclInObjCContainer() && D->getAccess() == AS_none && !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && @@ -253,9 +267,10 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - D->RedeclLink.getNext() == D && + D->getFirstDeclaration() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && + !D->isTopLevelDeclInObjCContainer() && D->getAccess() == AS_none && !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && @@ -289,14 +304,33 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { } void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { - VisitDeclaratorDecl(D); VisitRedeclarable(D); + VisitDeclaratorDecl(D); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Record.push_back(D->getIdentifierNamespace()); + + // FunctionDecl's body is handled last at ASTWriterDecl::Visit, + // after everything else is written. + + Record.push_back(D->getStorageClass()); // FIXME: stable encoding + Record.push_back(D->getStorageClassAsWritten()); + Record.push_back(D->IsInline); + Record.push_back(D->isInlineSpecified()); + Record.push_back(D->isVirtualAsWritten()); + Record.push_back(D->isPure()); + Record.push_back(D->hasInheritedPrototype()); + Record.push_back(D->hasWrittenPrototype()); + Record.push_back(D->isDeletedAsWritten()); + Record.push_back(D->isTrivial()); + Record.push_back(D->isDefaulted()); + Record.push_back(D->isExplicitlyDefaulted()); + Record.push_back(D->hasImplicitReturnZero()); + Record.push_back(D->isConstexpr()); + Writer.AddSourceLocation(D->getLocEnd(), Record); + Record.push_back(D->getTemplatedKind()); switch (D->getTemplatedKind()) { - default: llvm_unreachable("Unhandled TemplatedKind!"); case FunctionDecl::TK_NonTemplate: break; case FunctionDecl::TK_FunctionTemplate: @@ -360,25 +394,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { } } - // FunctionDecl's body is handled last at ASTWriterDecl::Visit, - // after everything else is written. - - Record.push_back(D->getStorageClass()); // FIXME: stable encoding - Record.push_back(D->getStorageClassAsWritten()); - Record.push_back(D->IsInline); - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isVirtualAsWritten()); - Record.push_back(D->isPure()); - Record.push_back(D->hasInheritedPrototype()); - Record.push_back(D->hasWrittenPrototype()); - Record.push_back(D->isDeletedAsWritten()); - Record.push_back(D->isTrivial()); - Record.push_back(D->isDefaulted()); - Record.push_back(D->isExplicitlyDefaulted()); - Record.push_back(D->hasImplicitReturnZero()); - Record.push_back(D->isConstexpr()); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->param_size()); for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); P != PEnd; ++P) @@ -441,39 +456,48 @@ void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { } void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + VisitRedeclarable(D); VisitObjCContainerDecl(D); Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); - Writer.AddDeclRef(D->getSuperClass(), Record); - // Write out the protocols that are directly referenced by the @interface. - Record.push_back(D->ReferencedProtocols.size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), - PEnd = D->protocol_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), + Record.push_back(D->isThisDeclarationADefinition()); + if (D->isThisDeclarationADefinition()) { + // Write the DefinitionData + ObjCInterfaceDecl::DefinitionData &Data = D->data(); + + Writer.AddDeclRef(D->getSuperClass(), Record); + Writer.AddSourceLocation(D->getSuperClassLoc(), Record); + Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record); + + // Write out the protocols that are directly referenced by the @interface. + Record.push_back(Data.ReferencedProtocols.size()); + for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), + PEnd = D->protocol_end(); + P != PEnd; ++P) + Writer.AddDeclRef(*P, Record); + for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - - // Write out the protocols that are transitively referenced. - Record.push_back(D->AllReferencedProtocols.size()); - for (ObjCList<ObjCProtocolDecl>::iterator - P = D->AllReferencedProtocols.begin(), - PEnd = D->AllReferencedProtocols.end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); + PL != PLEnd; ++PL) + Writer.AddSourceLocation(*PL, Record); + + // Write out the protocols that are transitively referenced. + Record.push_back(Data.AllReferencedProtocols.size()); + for (ObjCList<ObjCProtocolDecl>::iterator + P = Data.AllReferencedProtocols.begin(), + PEnd = Data.AllReferencedProtocols.end(); + P != PEnd; ++P) + Writer.AddDeclRef(*P, Record); + + if (ObjCCategoryDecl *Cat = D->getCategoryList()) { + // Ensure that we write out the set of categories for this class. + Writer.ObjCClassesWithCategories.insert(D); + + // Make sure that the categories get serialized. + for (; Cat; Cat = Cat->getNextClassCategory()) + (void)Writer.GetDeclRef(Cat); + } + } - // Write out the ivars. - Record.push_back(D->ivar_size()); - for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), - IEnd = D->ivar_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - Writer.AddDeclRef(D->getCategoryList(), Record); - Record.push_back(D->isForwardDecl()); - Record.push_back(D->isImplicitInterfaceDecl()); - Writer.AddSourceLocation(D->getSuperClassLoc(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); Code = serialization::DECL_OBJC_INTERFACE; } @@ -498,17 +522,21 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { } void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + VisitRedeclarable(D); VisitObjCContainerDecl(D); - Record.push_back(D->isForwardDecl()); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); + + Record.push_back(D->isThisDeclarationADefinition()); + if (D->isThisDeclarationADefinition()) { + Record.push_back(D->protocol_size()); + for (ObjCProtocolDecl::protocol_iterator + I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) + Writer.AddDeclRef(*I, Record); + for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), + PLEnd = D->protocol_loc_end(); + PL != PLEnd; ++PL) + Writer.AddSourceLocation(*PL, Record); + } + Code = serialization::DECL_OBJC_PROTOCOL; } @@ -517,28 +545,11 @@ void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { Code = serialization::DECL_OBJC_AT_DEFS_FIELD; } -void ASTDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { - VisitDecl(D); - Writer.AddDeclRef(D->getForwardInterfaceDecl(), Record); - Writer.AddSourceLocation(D->getForwardDecl()->getLocation(), Record); - Code = serialization::DECL_OBJC_CLASS; -} - -void ASTDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { - VisitDecl(D); - Record.push_back(D->protocol_size()); - for (ObjCForwardProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCForwardProtocolDecl::protocol_loc_iterator - PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Code = serialization::DECL_OBJC_FORWARD_PROTOCOL; -} - void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { VisitObjCContainerDecl(D); + Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); + Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record); + Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Writer.AddDeclRef(D->getClassInterface(), Record); Record.push_back(D->protocol_size()); for (ObjCCategoryDecl::protocol_iterator @@ -548,9 +559,7 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); PL != PLEnd; ++PL) Writer.AddSourceLocation(*PL, Record); - Writer.AddDeclRef(D->getNextClassCategory(), Record); Record.push_back(D->hasSynthBitfield()); - Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); Code = serialization::DECL_OBJC_CATEGORY; } @@ -563,6 +572,7 @@ void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { VisitNamedDecl(D); Writer.AddSourceLocation(D->getAtLoc(), Record); + Writer.AddSourceLocation(D->getLParenLoc(), Record); Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); // FIXME: stable encoding Record.push_back((unsigned)D->getPropertyAttributes()); @@ -586,12 +596,15 @@ void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { VisitObjCImplDecl(D); Writer.AddIdentifierRef(D->getIdentifier(), Record); + Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); Code = serialization::DECL_OBJC_CATEGORY_IMPL; } void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); Writer.AddDeclRef(D->getSuperClass(), Record); + Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record); + Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers, Record); Record.push_back(D->hasSynthBitfield()); @@ -625,6 +638,7 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { !D->isUsed(false) && !D->isInvalidDecl() && !D->isReferenced() && + !D->isTopLevelDeclInObjCContainer() && !D->isModulePrivate() && !D->getBitWidth() && !D->hasInClassInitializer() && @@ -649,19 +663,22 @@ void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { } void ASTDeclWriter::VisitVarDecl(VarDecl *D) { - VisitDeclaratorDecl(D); VisitRedeclarable(D); + VisitDeclaratorDecl(D); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->getStorageClassAsWritten()); Record.push_back(D->isThreadSpecified()); - Record.push_back(D->hasCXXDirectInitializer()); + Record.push_back(D->getInitStyle()); Record.push_back(D->isExceptionVariable()); Record.push_back(D->isNRVOVariable()); Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->isARCPseudoStrong()); - Record.push_back(D->getInit() ? 1 : 0); - if (D->getInit()) + if (D->getInit()) { + Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2)); Writer.AddStmt(D->getInit()); + } else { + Record.push_back(0); + } MemberSpecializationInfo *SpecInfo = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0; @@ -677,12 +694,13 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isUsed(false) && !D->isInvalidDecl() && !D->isReferenced() && + !D->isTopLevelDeclInObjCContainer() && D->getAccess() == AS_none && !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier && !D->hasExtInfo() && - D->RedeclLink.getNext() == D && - !D->hasCXXDirectInitializer() && + D->getFirstDeclaration() == D->getMostRecentDecl() && + D->getInitStyle() == VarDecl::CInit && D->getInit() == 0 && !isa<ParmVarDecl>(D) && !SpecInfo) @@ -718,10 +736,12 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { !D->hasExtInfo() && !D->isImplicit() && !D->isUsed(false) && + !D->isInvalidDecl() && + !D->isReferenced() && D->getAccess() == AS_none && !D->isModulePrivate() && D->getStorageClass() == 0 && - !D->hasCXXDirectInitializer() && // Can params have this ever? + D->getInitStyle() == VarDecl::CInit && // Can params have anything else? D->getFunctionScopeDepth() == 0 && D->getObjCDeclQualifier() == 0 && !D->isKNRPromoted() && @@ -732,11 +752,10 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { // Check things we know are true of *every* PARM_VAR_DECL, which is more than // just us assuming it. - assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls"); assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread"); assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); - assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl"); + assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl"); assert(!D->isStaticDataMember() && "PARM_VAR_DECL can't be static data member"); } @@ -791,18 +810,14 @@ void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { + VisitRedeclarable(D); VisitNamedDecl(D); Record.push_back(D->isInline()); Writer.AddSourceLocation(D->getLocStart(), Record); Writer.AddSourceLocation(D->getRBraceLoc(), Record); - Writer.AddDeclRef(D->getNextNamespace(), Record); - // Only write one reference--original or anonymous - Record.push_back(D->isOriginalNamespace()); if (D->isOriginalNamespace()) Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - else - Writer.AddDeclRef(D->getOriginalNamespace(), Record); Code = serialization::DECL_NAMESPACE; if (Writer.hasChain() && !D->isOriginalNamespace() && @@ -811,9 +826,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { Writer.AddUpdatedDeclContext(NS); // Make sure all visible decls are written. They will be recorded later. - NS->lookup(DeclarationName()); - StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(NS->getLookupPtr()); - if (Map) { + if (StoredDeclsMap *Map = NS->buildLookup()) { for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); D != DEnd; ++D) { DeclContext::lookup_result Result = D->second.getLookupResult(); @@ -825,7 +838,8 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { } } - if (Writer.hasChain() && D->isAnonymousNamespace() && !D->getNextNamespace()){ + if (Writer.hasChain() && D->isAnonymousNamespace() && + D == D->getMostRecentDecl()) { // This is a most recent reopening of the anonymous namespace. If its parent // is in a previous PCH (or is the TU), mark that parent for update, because // the original namespace always points to the latest re-opening of its @@ -854,7 +868,7 @@ void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { Writer.AddSourceLocation(D->getUsingLocation(), Record); Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); - Writer.AddDeclRef(D->FirstUsingShadow, Record); + Writer.AddDeclRef(D->FirstUsingShadow.getPointer(), Record); Record.push_back(D->isTypeName()); Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record); Code = serialization::DECL_USING; @@ -896,12 +910,8 @@ void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { VisitRecordDecl(D); - - CXXRecordDecl *DefinitionDecl = 0; - if (D->DefinitionData) - DefinitionDecl = D->DefinitionData->Definition; - Writer.AddDeclRef(DefinitionDecl, Record); - if (D == DefinitionDecl) + Record.push_back(D->isThisDeclarationADefinition()); + if (D->isThisDeclarationADefinition()) Writer.AddCXXDefinitionData(D, Record); enum { @@ -964,6 +974,23 @@ void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { Code = serialization::DECL_CXX_CONVERSION; } +void ASTDeclWriter::VisitImportDecl(ImportDecl *D) { + VisitDecl(D); + ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs(); + Record.push_back(!IdentifierLocs.empty()); + if (IdentifierLocs.empty()) { + Writer.AddSourceLocation(D->getLocEnd(), Record); + Record.push_back(1); + } else { + for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I) + Writer.AddSourceLocation(IdentifierLocs[I], Record); + Record.push_back(IdentifierLocs.size()); + } + // Note: the number of source locations must always be the last element in + // the record. + Code = serialization::DECL_IMPORT; +} + void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { VisitDecl(D); Writer.AddSourceLocation(D->getColonLoc(), Record); @@ -1005,36 +1032,17 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { } void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { + VisitRedeclarable(D); + // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that // getCommonPtr() can be used while this is still initializing. - - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - if (D->getPreviousDeclaration()) - Writer.AddDeclRef(D->getFirstDeclaration(), Record); - - if (D->getPreviousDeclaration() == 0) { - // This TemplateDecl owns the CommonPtr; write it. - assert(D->isCanonicalDecl()); - + if (D->isFirstDeclaration()) { + // This declaration owns the 'common' pointer, so serialize that data now. Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); if (D->getInstantiatedFromMemberTemplate()) Record.push_back(D->isMemberSpecialization()); - - Writer.AddDeclRef(D->getCommonPtr()->Latest, Record); - } else { - RedeclarableTemplateDecl *First = D->getFirstDeclaration(); - assert(First != D); - // If this is a most recent redeclaration that is pointed to by a first decl - // in a chained PCH, keep track of the association with the map so we can - // update the first decl during AST reading. - if (First->getMostRecentDeclaration() == D && - First->isFromASTFile() && !D->isFromASTFile()) { - assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end() - && "The latest is already set"); - Writer.FirstLatestDecls[First] = D; - } } - + VisitTemplateDecl(D); Record.push_back(D->getIdentifierNamespace()); } @@ -1042,7 +1050,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->getPreviousDeclaration() == 0) { + if (D->isFirstDeclaration()) { typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy; CTSDSetTy &CTSDSet = D->getSpecializations(); Record.push_back(CTSDSet.size()); @@ -1111,7 +1119,7 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( Record.push_back(D->getSequenceNumber()); // These are read/set from/to the first declaration. - if (D->getPreviousDeclaration() == 0) { + if (D->getPreviousDecl() == 0) { Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); Record.push_back(D->isMemberSpecialization()); } @@ -1130,7 +1138,7 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->getPreviousDeclaration() == 0) { + if (D->isFirstDeclaration()) { // This FunctionTemplateDecl owns the CommonPtr; write it. // Write the function specialization declarations. @@ -1230,31 +1238,23 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, template <typename T> void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { - enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; - if (D->RedeclLink.getNext() == D) { - Record.push_back(NoRedeclaration); - } else { - if (D->RedeclLink.NextIsPrevious()) { - Record.push_back(PointsToPrevious); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Writer.AddDeclRef(D->getFirstDeclaration(), Record); - } else { - Record.push_back(PointsToLatest); - Writer.AddDeclRef(D->RedeclLink.getPointer(), Record); - } - } - T *First = D->getFirstDeclaration(); - T *ThisDecl = static_cast<T*>(D); - // If this is a most recent redeclaration that is pointed to by a first decl - // in a chained PCH, keep track of the association with the map so we can - // update the first decl during AST reading. - if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl && - First->isFromASTFile() && !ThisDecl->isFromASTFile()) { - assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end() - && "The latest is already set"); - Writer.FirstLatestDecls[First] = ThisDecl; + if (First->getMostRecentDecl() != First) { + // There is more than one declaration of this entity, so we will need to + // write a redeclaration chain. + Writer.AddDeclRef(First, Record); + Writer.Redeclarations.insert(First); + + // Make sure that we serialize both the previous and the most-recent + // declarations, which (transitively) ensures that all declarations in the + // chain get serialized. + (void)Writer.GetDeclRef(D->getPreviousDecl()); + (void)Writer.GetDeclRef(First->getMostRecentDecl()); + } else { + // We use the sentinel value 0 to indicate an only declaration. + Record.push_back(0); } + } //===----------------------------------------------------------------------===// @@ -1272,14 +1272,15 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1303,14 +1304,15 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1334,25 +1336,26 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Abbreviation for DECL_ENUM Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // TagDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind @@ -1380,25 +1383,26 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Abbreviation for DECL_RECORD Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref - // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // TagDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind @@ -1420,17 +1424,20 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Abbreviation for DECL_PARM_VAR Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1440,7 +1447,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // VarDecl - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration Abv->Add(BitCodeAbbrevOp(0)); // StorageClass Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified @@ -1468,17 +1474,20 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Abbreviation for DECL_TYPEDEF Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1493,17 +1502,20 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Abbreviation for DECL_VAR Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) + Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced + Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1513,7 +1525,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // VarDecl - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClassAsWritten Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isThreadSpecified @@ -1547,6 +1558,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //RefersToEnclosingLocal Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(Abv); @@ -1629,6 +1641,20 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { RecordData Record; ASTDeclWriter W(*this, Context, Record); + // Determine the ID for this declaration. + serialization::DeclID ID; + if (D->isFromASTFile()) + ID = getDeclID(D); + else { + serialization::DeclID &IDR = DeclIDs[D]; + if (IDR == 0) + IDR = NextDeclID++; + + ID= IDR; + } + + bool isReplacingADecl = ID < FirstDeclID; + // If this declaration is also a DeclContext, write blocks for the // declarations that lexically stored inside its context and those // declarations that are visible from its context. These blocks @@ -1638,29 +1664,38 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { uint64_t VisibleOffset = 0; DeclContext *DC = dyn_cast<DeclContext>(D); if (DC) { + if (isReplacingADecl) { + // It is replacing a decl from a chained PCH; make sure that the + // DeclContext is fully loaded. + if (DC->hasExternalLexicalStorage()) + DC->LoadLexicalDeclsFromExternalStorage(); + if (DC->hasExternalVisibleStorage()) + Chain->completeVisibleDeclsMap(DC); + } LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); } - - // Determine the ID for this declaration - serialization::DeclID &IDR = DeclIDs[D]; - if (IDR == 0) - IDR = NextDeclID++; - serialization::DeclID ID = IDR; - - if (ID < FirstDeclID) { + + if (isReplacingADecl) { // We're replacing a decl in a previous file. - ReplacedDecls.push_back(std::make_pair(ID, Stream.GetCurrentBitNo())); + ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(), + D->getLocation())); } else { unsigned Index = ID - FirstDeclID; // Record the offset for this declaration + SourceLocation Loc = D->getLocation(); if (DeclOffsets.size() == Index) - DeclOffsets.push_back(Stream.GetCurrentBitNo()); + DeclOffsets.push_back(DeclOffset(Loc, Stream.GetCurrentBitNo())); else if (DeclOffsets.size() < Index) { DeclOffsets.resize(Index+1); - DeclOffsets[Index] = Stream.GetCurrentBitNo(); + DeclOffsets[Index].setLocation(Loc); + DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo(); } + + SourceManager &SM = Context.getSourceManager(); + if (Loc.isValid() && SM.isLocalSourceLocation(Loc)) + associateDeclWithFile(D, ID); } // Build and emit a record for this declaration diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp index 7e2d45c..827caa0 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp @@ -34,9 +34,8 @@ namespace clang { ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record) : Writer(Writer), Record(Record) { } - - void - AddExplicitTemplateArgumentList(const ASTTemplateArgumentListInfo &Args); + + void AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args); void VisitStmt(Stmt *S); #define STMT(Type, Base) \ @@ -46,7 +45,8 @@ namespace clang { } void ASTStmtWriter:: -AddExplicitTemplateArgumentList(const ASTTemplateArgumentListInfo &Args) { +AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args) { + Writer.AddSourceLocation(Args.getTemplateKeywordLoc(), Record); Writer.AddSourceLocation(Args.LAngleLoc, Record); Writer.AddSourceLocation(Args.RAngleLoc, Record); for (unsigned i=0; i != Args.NumTemplateArgs; ++i) @@ -264,17 +264,18 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { Record.push_back(E->hasQualifier()); Record.push_back(E->getDecl() != E->getFoundDecl()); - Record.push_back(E->hasExplicitTemplateArgs()); + Record.push_back(E->hasTemplateKWAndArgsInfo()); Record.push_back(E->hadMultipleCandidates()); + Record.push_back(E->refersToEnclosingLocal()); - if (E->hasExplicitTemplateArgs()) { + if (E->hasTemplateKWAndArgsInfo()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); Record.push_back(NumTemplateArgs); } DeclarationName::NameKind nk = (E->getDecl()->getDeclName().getNameKind()); - if ((!E->hasExplicitTemplateArgs()) && (!E->hasQualifier()) && + if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && (E->getDecl() == E->getFoundDecl()) && nk == DeclarationName::Identifier) { AbbrevToUse = Writer.getDeclRefExprAbbrev(); @@ -286,8 +287,8 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { if (E->getDecl() != E->getFoundDecl()) Writer.AddDeclRef(E->getFoundDecl(), Record); - if (E->hasExplicitTemplateArgs()) - AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs()); + if (E->hasTemplateKWAndArgsInfo()) + AddTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo()); Writer.AddDeclRef(E->getDecl(), Record); Writer.AddSourceLocation(E->getLocation(), Record); @@ -331,7 +332,7 @@ void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) { // StringLiteral. However, we can't do so now because we have no // provision for coping with abbreviations when we're jumping around // the AST file during deserialization. - Record.append(E->getString().begin(), E->getString().end()); + Record.append(E->getBytes().begin(), E->getBytes().end()); for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) Writer.AddSourceLocation(E->getStrTokenLoc(I), Record); Code = serialization::EXPR_STRING_LITERAL; @@ -449,8 +450,9 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { if (E->hasQualifier()) Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); - Record.push_back(E->hasExplicitTemplateArgs()); - if (E->hasExplicitTemplateArgs()) { + Record.push_back(E->HasTemplateKWAndArgsInfo); + if (E->HasTemplateKWAndArgsInfo) { + Writer.AddSourceLocation(E->getTemplateKeywordLoc(), Record); unsigned NumTemplateArgs = E->getNumTemplateArgs(); Record.push_back(NumTemplateArgs); Writer.AddSourceLocation(E->getLAngleLoc(), Record); @@ -597,6 +599,7 @@ void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { else Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); Record.push_back(E->hadArrayRangeDesignator()); + Record.push_back(E->initializesStdInitializerList()); Record.push_back(E->getNumInits()); if (isArrayFiller) { // ArrayFiller may have filled "holes" due to designated initializer. @@ -710,15 +713,6 @@ void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) { Code = serialization::EXPR_BLOCK; } -void ASTStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getDecl(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isByRef()); - Record.push_back(E->isConstQualAdded()); - Code = serialization::EXPR_BLOCK_DECL_REF; -} - void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); Record.push_back(E->getNumAssocs()); @@ -736,19 +730,32 @@ void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Code = serialization::EXPR_GENERIC_SELECTION; } +void ASTStmtWriter::VisitPseudoObjectExpr(PseudoObjectExpr *E) { + VisitExpr(E); + Record.push_back(E->getNumSemanticExprs()); + + // Push the result index. Currently, this needs to exactly match + // the encoding used internally for ResultIndex. + unsigned result = E->getResultExprIndex(); + result = (result == PseudoObjectExpr::NoResult ? 0 : result + 1); + Record.push_back(result); + + Writer.AddStmt(E->getSyntacticForm()); + for (PseudoObjectExpr::semantics_iterator + i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { + Writer.AddStmt(*i); + } + Code = serialization::EXPR_PSEUDO_OBJECT; +} + void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) { VisitExpr(E); Record.push_back(E->getOp()); - Writer.AddStmt(E->getPtr()); - Writer.AddStmt(E->getOrder()); - if (E->getOp() != AtomicExpr::Load) - Writer.AddStmt(E->getVal1()); - if (E->isCmpXChg()) { - Writer.AddStmt(E->getOrderFail()); - Writer.AddStmt(E->getVal2()); - } + for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) + Writer.AddStmt(E->getSubExprs()[I]); Writer.AddSourceLocation(E->getBuiltinLoc(), Record); Writer.AddSourceLocation(E->getRParenLoc(), Record); + Code = serialization::EXPR_ATOMIC; } //===----------------------------------------------------------------------===// @@ -762,6 +769,46 @@ void ASTStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { Code = serialization::EXPR_OBJC_STRING_LITERAL; } +void ASTStmtWriter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) { + VisitExpr(E); + Writer.AddStmt(E->getNumber()); + Writer.AddDeclRef(E->getObjCNumericLiteralMethod(), Record); + Writer.AddSourceLocation(E->getAtLoc(), Record); + Code = serialization::EXPR_OBJC_NUMERIC_LITERAL; +} + +void ASTStmtWriter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + VisitExpr(E); + Record.push_back(E->getNumElements()); + for (unsigned i = 0; i < E->getNumElements(); i++) + Writer.AddStmt(E->getElement(i)); + Writer.AddDeclRef(E->getArrayWithObjectsMethod(), Record); + Writer.AddSourceRange(E->getSourceRange(), Record); + Code = serialization::EXPR_OBJC_ARRAY_LITERAL; +} + +void ASTStmtWriter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + VisitExpr(E); + Record.push_back(E->getNumElements()); + Record.push_back(E->HasPackExpansions); + for (unsigned i = 0; i < E->getNumElements(); i++) { + ObjCDictionaryElement Element = E->getKeyValueElement(i); + Writer.AddStmt(Element.Key); + Writer.AddStmt(Element.Value); + if (E->HasPackExpansions) { + Writer.AddSourceLocation(Element.EllipsisLoc, Record); + unsigned NumExpansions = 0; + if (Element.NumExpansions) + NumExpansions = *Element.NumExpansions + 1; + Record.push_back(NumExpansions); + } + } + + Writer.AddDeclRef(E->getDictWithObjectsMethod(), Record); + Writer.AddSourceRange(E->getSourceRange(), Record); + Code = serialization::EXPR_OBJC_DICTIONARY_LITERAL; +} + void ASTStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { VisitExpr(E); Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record); @@ -798,6 +845,7 @@ void ASTStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { VisitExpr(E); + Record.push_back(E->SetterAndMethodRefFlags.getInt()); Record.push_back(E->isImplicitProperty()); if (E->isImplicitProperty()) { Writer.AddDeclRef(E->getImplicitPropertyGetter(), Record); @@ -821,12 +869,24 @@ void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR; } +void ASTStmtWriter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { + VisitExpr(E); + Writer.AddSourceLocation(E->getRBracket(), Record); + Writer.AddStmt(E->getBaseExpr()); + Writer.AddStmt(E->getKeyExpr()); + Writer.AddDeclRef(E->getAtIndexMethodDecl(), Record); + Writer.AddDeclRef(E->setAtIndexMethodDecl(), Record); + + Code = serialization::EXPR_OBJC_SUBSCRIPT_REF_EXPR; +} + void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { VisitExpr(E); Record.push_back(E->getNumArgs()); Record.push_back(E->getNumStoredSelLocs()); Record.push_back(E->SelLocsKind); Record.push_back(E->isDelegateInitCall()); + Record.push_back(E->IsImplicit); Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding switch (E->getReceiverKind()) { case ObjCMessageExpr::Instance: @@ -921,6 +981,13 @@ void ASTStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { Code = serialization::STMT_OBJC_AT_THROW; } +void ASTStmtWriter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { + VisitExpr(E); + Record.push_back(E->getValue()); + Writer.AddSourceLocation(E->getLocation(), Record); + Code = serialization::EXPR_OBJC_BOOL_LITERAL; +} + //===----------------------------------------------------------------------===// // C++ Expressions and Statements. //===----------------------------------------------------------------------===// @@ -957,6 +1024,16 @@ void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { Code = serialization::STMT_CXX_FOR_RANGE; } +void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getKeywordLoc(), Record); + Record.push_back(S->isIfExists()); + Writer.AddNestedNameSpecifierLoc(S->getQualifierLoc(), Record); + Writer.AddDeclarationNameInfo(S->getNameInfo(), Record); + Writer.AddStmt(S->getSubStmt()); + Code = serialization::STMT_MS_DEPENDENT_EXISTS; +} + void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); Record.push_back(E->getOperator()); @@ -989,6 +1066,38 @@ void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { Code = serialization::EXPR_CXX_TEMPORARY_OBJECT; } +void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { + VisitExpr(E); + Record.push_back(E->NumCaptures); + unsigned NumArrayIndexVars = 0; + if (E->HasArrayIndexVars) + NumArrayIndexVars = E->getArrayIndexStarts()[E->NumCaptures]; + Record.push_back(NumArrayIndexVars); + Writer.AddSourceRange(E->IntroducerRange, Record); + Record.push_back(E->CaptureDefault); // FIXME: stable encoding + Record.push_back(E->ExplicitParams); + Record.push_back(E->ExplicitResultType); + Writer.AddSourceLocation(E->ClosingBrace, Record); + + // Add capture initializers. + for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(), + CEnd = E->capture_init_end(); + C != CEnd; ++C) { + Writer.AddStmt(*C); + } + + // Add array index variables, if any. + if (NumArrayIndexVars) { + Record.append(E->getArrayIndexStarts(), + E->getArrayIndexStarts() + E->NumCaptures + 1); + VarDecl **ArrayIndexVars = E->getArrayIndexVars(); + for (unsigned I = 0; I != NumArrayIndexVars; ++I) + Writer.AddDeclRef(ArrayIndexVars[I], Record); + } + + Code = serialization::EXPR_LAMBDA; +} + void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { VisitExplicitCastExpr(E); Writer.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc()), @@ -1022,6 +1131,12 @@ void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; } +void ASTStmtWriter::VisitUserDefinedLiteral(UserDefinedLiteral *E) { + VisitCallExpr(E); + Writer.AddSourceLocation(E->UDSuffixLoc, Record); + Code = serialization::EXPR_USER_DEFINED_LITERAL; +} + void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { VisitExpr(E); Record.push_back(E->getValue()); @@ -1093,25 +1208,20 @@ void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { VisitExpr(E); Record.push_back(E->isGlobalNew()); - Record.push_back(E->hasInitializer()); - Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->isArray()); - Record.push_back(E->hadMultipleCandidates()); + Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->getNumPlacementArgs()); - Record.push_back(E->getNumConstructorArgs()); + Record.push_back(E->StoredInitializationStyle); Writer.AddDeclRef(E->getOperatorNew(), Record); Writer.AddDeclRef(E->getOperatorDelete(), Record); - Writer.AddDeclRef(E->getConstructor(), Record); Writer.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo(), Record); Writer.AddSourceRange(E->getTypeIdParens(), Record); Writer.AddSourceLocation(E->getStartLoc(), Record); - Writer.AddSourceLocation(E->getEndLoc(), Record); - Writer.AddSourceLocation(E->getConstructorLParen(), Record); - Writer.AddSourceLocation(E->getConstructorRParen(), Record); + Writer.AddSourceRange(E->getDirectInitRange(), Record); for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); I != e; ++I) Writer.AddStmt(*I); - + Code = serialization::EXPR_CXX_NEW; } @@ -1151,9 +1261,9 @@ void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) { VisitExpr(E); - Record.push_back(E->getNumTemporaries()); - for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i) - Writer.AddCXXTemporary(E->getTemporary(i), Record); + Record.push_back(E->getNumObjects()); + for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i) + Writer.AddDeclRef(E->getObject(i), Record); Writer.AddStmt(E->getSubExpr()); Code = serialization::EXPR_EXPR_WITH_CLEANUPS; @@ -1162,17 +1272,17 @@ void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) { void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ VisitExpr(E); - - // Don't emit anything here, hasExplicitTemplateArgs() must be + + // Don't emit anything here, HasTemplateKWAndArgsInfo must be // emitted first. - Record.push_back(E->hasExplicitTemplateArgs()); - if (E->hasExplicitTemplateArgs()) { - const ASTTemplateArgumentListInfo &Args = E->getExplicitTemplateArgs(); + Record.push_back(E->HasTemplateKWAndArgsInfo); + if (E->HasTemplateKWAndArgsInfo) { + const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo(); Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); + AddTemplateKWAndArgsInfo(Args); } - + if (!E->isImplicitAccess()) Writer.AddStmt(E->getBase()); else @@ -1189,14 +1299,15 @@ ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ void ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { VisitExpr(E); - - // Don't emit anything here, hasExplicitTemplateArgs() must be + + // Don't emit anything here, HasTemplateKWAndArgsInfo must be // emitted first. - Record.push_back(E->hasExplicitTemplateArgs()); - if (E->hasExplicitTemplateArgs()) { - const ASTTemplateArgumentListInfo &Args = E->getExplicitTemplateArgs(); + + Record.push_back(E->HasTemplateKWAndArgsInfo); + if (E->HasTemplateKWAndArgsInfo) { + const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo(); Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); + AddTemplateKWAndArgsInfo(Args); } Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); @@ -1219,13 +1330,15 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); - - // Don't emit anything here, hasExplicitTemplateArgs() must be emitted first. - Record.push_back(E->hasExplicitTemplateArgs()); - if (E->hasExplicitTemplateArgs()) { - const ASTTemplateArgumentListInfo &Args = E->getExplicitTemplateArgs(); + + // Don't emit anything here, HasTemplateKWAndArgsInfo must be + // emitted first. + + Record.push_back(E->HasTemplateKWAndArgsInfo); + if (E->HasTemplateKWAndArgsInfo) { + const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo(); Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); + AddTemplateKWAndArgsInfo(Args); } Record.push_back(E->getNumDecls()); @@ -1278,6 +1391,16 @@ void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { Code = serialization::EXPR_BINARY_TYPE_TRAIT; } +void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { + VisitExpr(E); + Record.push_back(E->TypeTraitExprBits.NumArgs); + Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding + Record.push_back(E->TypeTraitExprBits.Value); + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) + Writer.AddTypeSourceInfo(E->getArg(I), Record); + Code = serialization::EXPR_TYPE_TRAIT; +} + void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { VisitExpr(E); Record.push_back(E->getTrait()); @@ -1348,7 +1471,7 @@ void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); - Record.push_back(Writer.getOpaqueValueID(E)); + Writer.AddStmt(E->getSourceExpr()); Writer.AddSourceLocation(E->getLocation(), Record); Code = serialization::EXPR_OPAQUE_VALUE; } @@ -1435,15 +1558,11 @@ void ASTWriter::ClearSwitchCaseIDs() { SwitchCaseIDs.clear(); } -unsigned ASTWriter::getOpaqueValueID(OpaqueValueExpr *e) { - unsigned &entry = OpaqueValues[e]; - if (!entry) entry = OpaqueValues.size(); - return entry; -} - /// \brief Write the given substatement or subexpression to the /// bitstream. -void ASTWriter::WriteSubStmt(Stmt *S) { +void ASTWriter::WriteSubStmt(Stmt *S, + llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries, + llvm::DenseSet<Stmt *> &ParentStmts) { RecordData Record; ASTStmtWriter Writer(*this, Record); ++NumStatements; @@ -1453,6 +1572,32 @@ void ASTWriter::WriteSubStmt(Stmt *S) { return; } + llvm::DenseMap<Stmt *, uint64_t>::iterator I = SubStmtEntries.find(S); + if (I != SubStmtEntries.end()) { + Record.push_back(I->second); + Stream.EmitRecord(serialization::STMT_REF_PTR, Record); + return; + } + +#ifndef NDEBUG + assert(!ParentStmts.count(S) && "There is a Stmt cycle!"); + + struct ParentStmtInserterRAII { + Stmt *S; + llvm::DenseSet<Stmt *> &ParentStmts; + + ParentStmtInserterRAII(Stmt *S, llvm::DenseSet<Stmt *> &ParentStmts) + : S(S), ParentStmts(ParentStmts) { + ParentStmts.insert(S); + } + ~ParentStmtInserterRAII() { + ParentStmts.erase(S); + } + }; + + ParentStmtInserterRAII ParentStmtInserter(S, ParentStmts); +#endif + // Redirect ASTWriter::AddStmt to collect sub stmts. SmallVector<Stmt *, 16> SubStmts; CollectedStmts = &SubStmts; @@ -1478,9 +1623,11 @@ void ASTWriter::WriteSubStmt(Stmt *S) { // This simplifies reading and allows to store a variable number of sub stmts // without knowing it in advance. while (!SubStmts.empty()) - WriteSubStmt(SubStmts.pop_back_val()); + WriteSubStmt(SubStmts.pop_back_val(), SubStmtEntries, ParentStmts); Stream.EmitRecord(Writer.Code, Record, Writer.AbbrevToUse); + + SubStmtEntries[S] = Stream.GetCurrentBitNo(); } /// \brief Flush all of the statements that have been added to the @@ -1488,8 +1635,13 @@ void ASTWriter::WriteSubStmt(Stmt *S) { void ASTWriter::FlushStmts() { RecordData Record; + // We expect to be the only consumer of the two temporary statement maps, + // assert that they are empty. + assert(SubStmtEntries.empty() && "unexpected entries in sub stmt map"); + assert(ParentStmts.empty() && "unexpected entries in parent stmt map"); + for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { - WriteSubStmt(StmtsToEmit[I]); + WriteSubStmt(StmtsToEmit[I], SubStmtEntries, ParentStmts); assert(N == StmtsToEmit.size() && "Substatement written via AddStmt rather than WriteSubStmt!"); @@ -1498,6 +1650,9 @@ void ASTWriter::FlushStmts() { // expression records that follow this one are part of a different // expression. Stream.EmitRecord(serialization::STMT_STOP, Record); + + SubStmtEntries.clear(); + ParentStmts.clear(); } StmtsToEmit.clear(); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp b/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp deleted file mode 100644 index 5fcf11a..0000000 --- a/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp +++ /dev/null @@ -1,240 +0,0 @@ -//===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ChainedIncludesSource class, which converts headers -// to chained PCHs in memory, mainly used for testing. -// -//===----------------------------------------------------------------------===// - -#include "clang/Serialization/ChainedIncludesSource.h" -#include "clang/Serialization/ASTReader.h" -#include "clang/Serialization/ASTWriter.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/ASTUnit.h" -#include "clang/Parse/ParseAST.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/Support/MemoryBuffer.h" - -using namespace clang; - -static ASTReader *createASTReader(CompilerInstance &CI, - StringRef pchFile, - SmallVector<llvm::MemoryBuffer *, 4> &memBufs, - SmallVector<std::string, 4> &bufNames, - ASTDeserializationListener *deserialListener = 0) { - Preprocessor &PP = CI.getPreprocessor(); - llvm::OwningPtr<ASTReader> Reader; - Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"", - /*DisableValidation=*/true)); - for (unsigned ti = 0; ti < bufNames.size(); ++ti) { - StringRef sr(bufNames[ti]); - Reader->addInMemoryBuffer(sr, memBufs[ti]); - } - Reader->setDeserializationListener(deserialListener); - switch (Reader->ReadAST(pchFile, serialization::MK_PCH)) { - case ASTReader::Success: - // Set the predefines buffer as suggested by the PCH reader. - PP.setPredefines(Reader->getSuggestedPredefines()); - return Reader.take(); - - case ASTReader::Failure: - case ASTReader::IgnorePCH: - break; - } - return 0; -} - -ChainedIncludesSource::~ChainedIncludesSource() { - for (unsigned i = 0, e = CIs.size(); i != e; ++i) - delete CIs[i]; -} - -ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { - - std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes; - assert(!includes.empty() && "No '-chain-include' in options!"); - - llvm::OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource()); - InputKind IK = CI.getFrontendOpts().Inputs[0].first; - - SmallVector<llvm::MemoryBuffer *, 4> serialBufs; - SmallVector<std::string, 4> serialBufNames; - - for (unsigned i = 0, e = includes.size(); i != e; ++i) { - bool firstInclude = (i == 0); - llvm::OwningPtr<CompilerInvocation> CInvok; - CInvok.reset(new CompilerInvocation(CI.getInvocation())); - - CInvok->getPreprocessorOpts().ChainedIncludes.clear(); - CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear(); - CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear(); - CInvok->getPreprocessorOpts().DisablePCHValidation = true; - CInvok->getPreprocessorOpts().Includes.clear(); - CInvok->getPreprocessorOpts().MacroIncludes.clear(); - CInvok->getPreprocessorOpts().Macros.clear(); - - CInvok->getFrontendOpts().Inputs.clear(); - CInvok->getFrontendOpts().Inputs.push_back(std::make_pair(IK, includes[i])); - - TextDiagnosticPrinter *DiagClient = - new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); - llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags( - new DiagnosticsEngine(DiagID, DiagClient)); - - llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance()); - Clang->setInvocation(CInvok.take()); - Clang->setDiagnostics(Diags.getPtr()); - Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), - Clang->getTargetOpts())); - Clang->createFileManager(); - Clang->createSourceManager(Clang->getFileManager()); - Clang->createPreprocessor(); - Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), - &Clang->getPreprocessor()); - Clang->createASTContext(); - - SmallVector<char, 256> serialAST; - llvm::raw_svector_ostream OS(serialAST); - llvm::OwningPtr<ASTConsumer> consumer; - consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", - /*IsModule=*/false, /*isysroot=*/"", &OS)); - Clang->getASTContext().setASTMutationListener( - consumer->GetASTMutationListener()); - Clang->setASTConsumer(consumer.take()); - Clang->createSema(TU_Prefix, 0); - - if (firstInclude) { - Preprocessor &PP = Clang->getPreprocessor(); - PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), - PP.getLangOptions()); - } else { - assert(!serialBufs.empty()); - SmallVector<llvm::MemoryBuffer *, 4> bufs; - for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) { - bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( - StringRef(serialBufs[si]->getBufferStart(), - serialBufs[si]->getBufferSize()))); - } - std::string pchName = includes[i-1]; - llvm::raw_string_ostream os(pchName); - os << ".pch" << i-1; - os.flush(); - - serialBufNames.push_back(pchName); - - llvm::OwningPtr<ExternalASTSource> Reader; - - Reader.reset(createASTReader(*Clang, pchName, bufs, serialBufNames, - Clang->getASTConsumer().GetASTDeserializationListener())); - if (!Reader) - return 0; - Clang->getASTContext().setExternalSource(Reader); - } - - if (!Clang->InitializeSourceManager(includes[i])) - return 0; - - ParseAST(Clang->getSema()); - OS.flush(); - Clang->getDiagnosticClient().EndSourceFile(); - serialBufs.push_back( - llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(), - serialAST.size()))); - source->CIs.push_back(Clang.take()); - } - - assert(!serialBufs.empty()); - std::string pchName = includes.back() + ".pch-final"; - serialBufNames.push_back(pchName); - llvm::OwningPtr<ASTReader> Reader; - Reader.reset(createASTReader(CI, pchName, serialBufs, serialBufNames)); - if (!Reader) - return 0; - - source->FinalReader.reset(Reader.take()); - return source.take(); -} - -//===----------------------------------------------------------------------===// -// ExternalASTSource interface. -//===----------------------------------------------------------------------===// - -Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) { - return getFinalReader().GetExternalDecl(ID); -} -Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) { - return getFinalReader().GetExternalSelector(ID); -} -uint32_t ChainedIncludesSource::GetNumExternalSelectors() { - return getFinalReader().GetNumExternalSelectors(); -} -Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) { - return getFinalReader().GetExternalDeclStmt(Offset); -} -CXXBaseSpecifier * -ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { - return getFinalReader().GetExternalCXXBaseSpecifiers(Offset); -} -DeclContextLookupResult -ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) { - return getFinalReader().FindExternalVisibleDeclsByName(DC, Name); -} -ExternalLoadResult -ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Result) { - return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result); -} -void ChainedIncludesSource::CompleteType(TagDecl *Tag) { - return getFinalReader().CompleteType(Tag); -} -void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) { - return getFinalReader().CompleteType(Class); -} -void ChainedIncludesSource::StartedDeserializing() { - return getFinalReader().StartedDeserializing(); -} -void ChainedIncludesSource::FinishedDeserializing() { - return getFinalReader().FinishedDeserializing(); -} -void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) { - return getFinalReader().StartTranslationUnit(Consumer); -} -void ChainedIncludesSource::PrintStats() { - return getFinalReader().PrintStats(); -} -void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{ - for (unsigned i = 0, e = CIs.size(); i != e; ++i) { - if (const ExternalASTSource *eSrc = - CIs[i]->getASTContext().getExternalSource()) { - eSrc->getMemoryBufferSizes(sizes); - } - } - - getFinalReader().getMemoryBufferSizes(sizes); -} - -void ChainedIncludesSource::InitializeSema(Sema &S) { - return getFinalReader().InitializeSema(S); -} -void ChainedIncludesSource::ForgetSema() { - return getFinalReader().ForgetSema(); -} -std::pair<ObjCMethodList,ObjCMethodList> -ChainedIncludesSource::ReadMethodPool(Selector Sel) { - return getFinalReader().ReadMethodPool(Sel); -} -bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) { - return getFinalReader().LookupUnqualified(R, S); -} - diff --git a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp index a2534db..02aed10 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp @@ -1,4 +1,4 @@ -//===--- GeneratePCH.cpp - AST Consumer for PCH Generation ------*- C++ -*-===// +//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This file defines the CreatePCHGenerate function, which creates an -// ASTConsumer that generates a PCH file. +// This file defines the PCHGenerator, which as a SemaConsumer that generates +// a PCH file. // //===----------------------------------------------------------------------===// -#include "clang/Frontend/ASTConsumers.h" #include "clang/Serialization/ASTWriter.h" #include "clang/Sema/SemaConsumer.h" #include "clang/AST/ASTContext.h" @@ -28,10 +27,10 @@ using namespace clang; PCHGenerator::PCHGenerator(const Preprocessor &PP, StringRef OutputFile, - bool IsModule, + clang::Module *Module, StringRef isysroot, raw_ostream *OS) - : PP(PP), OutputFile(OutputFile), IsModule(IsModule), + : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()), Out(OS), SemaPtr(0), StatCalls(0), Stream(Buffer), Writer(Stream) { // Install a stat() listener to keep track of all of the stat() @@ -49,7 +48,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, IsModule, isysroot); + Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, Module, isysroot); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp index 0a721c4..16b95e2 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp @@ -20,8 +20,8 @@ using namespace clang; using namespace serialization; using namespace reader; -Module::Module(ModuleKind Kind) - : Kind(Kind), DirectlyImported(false), SizeInBits(0), +ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) + : Kind(Kind), DirectlyImported(false), Generation(Generation), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0), SLocEntryBaseOffset(0), SLocEntryOffsets(0), SLocFileOffsets(0), LocalNumIdentifiers(0), @@ -30,15 +30,17 @@ Module::Module(ModuleKind Kind) PreprocessedEntityOffsets(0), NumPreprocessedEntities(0), LocalNumHeaderFileInfos(0), HeaderFileInfoTableData(0), HeaderFileInfoTable(0), - HeaderFileFrameworkStrings(0), + HeaderFileFrameworkStrings(0), LocalNumSubmodules(0), BaseSubmoduleID(0), LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0), SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), DeclOffsets(0), BaseDeclID(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), + FileSortedDecls(0), RedeclarationsMap(0), LocalNumRedeclarationsInMap(0), + ObjCCategoriesMap(0), LocalNumObjCCategoriesInMap(0), LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0) {} -Module::~Module() { +ModuleFile::~ModuleFile() { for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(), E = DeclContextInfos.end(); I != E; ++I) { @@ -67,7 +69,7 @@ dumpLocalRemap(StringRef Name, } } -void Module::dump() { +void ModuleFile::dump() { llvm::errs() << "\nModule: " << FileName << "\n"; if (!Imports.empty()) { llvm::errs() << " Imports: "; @@ -87,7 +89,11 @@ void Module::dump() { llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n' << " Number of identifiers: " << LocalNumIdentifiers << '\n'; dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); - + + llvm::errs() << " Base submodule ID: " << BaseSubmoduleID << '\n' + << " Number of submodules: " << LocalNumSubmodules << '\n'; + dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap); + llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n' << " Number of selectors: " << LocalNumSelectors << '\n'; dumpLocalRemap("Selector ID local -> global map", SelectorRemap); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp index c4b1f71..ab364b7 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp @@ -23,7 +23,7 @@ using namespace clang; using namespace serialization; -Module *ModuleManager::lookup(StringRef Name) { +ModuleFile *ModuleManager::lookup(StringRef Name) { const FileEntry *Entry = FileMgr.getFile(Name); return Modules[Entry]; } @@ -33,21 +33,22 @@ llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { return InMemoryBuffers[Entry]; } -std::pair<Module *, bool> +std::pair<ModuleFile *, bool> ModuleManager::addModule(StringRef FileName, ModuleKind Type, - Module *ImportedBy, std::string &ErrorStr) { + ModuleFile *ImportedBy, unsigned Generation, + std::string &ErrorStr) { const FileEntry *Entry = FileMgr.getFile(FileName); if (!Entry && FileName != "-") { ErrorStr = "file not found"; - return std::make_pair(static_cast<Module*>(0), false); + return std::make_pair(static_cast<ModuleFile*>(0), false); } // Check whether we already loaded this module, before - Module *&ModuleEntry = Modules[Entry]; + ModuleFile *&ModuleEntry = Modules[Entry]; bool NewModule = false; if (!ModuleEntry) { // Allocate a new module. - Module *New = new Module(Type); + ModuleFile *New = new ModuleFile(Type, Generation); New->FileName = FileName.str(); Chain.push_back(New); NewModule = true; @@ -69,7 +70,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); if (!New->Buffer) - return std::make_pair(static_cast<Module*>(0), false); + return std::make_pair(static_cast<ModuleFile*>(0), false); } // Initialize the stream @@ -101,16 +102,16 @@ ModuleManager::~ModuleManager() { delete Chain[e - i - 1]; } -void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), +void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData) { unsigned N = size(); // Record the number of incoming edges for each module. When we // encounter a module with no incoming edges, push it into the queue // to seed the queue. - SmallVector<Module *, 4> Queue; + SmallVector<ModuleFile *, 4> Queue; Queue.reserve(N); - llvm::DenseMap<Module *, unsigned> UnusedIncomingEdges; + llvm::DenseMap<ModuleFile *, unsigned> UnusedIncomingEdges; for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { if (unsigned Size = (*M)->ImportedBy.size()) UnusedIncomingEdges[*M] = Size; @@ -118,10 +119,10 @@ void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), Queue.push_back(*M); } - llvm::SmallPtrSet<Module *, 4> Skipped; + llvm::SmallPtrSet<ModuleFile *, 4> Skipped; unsigned QueueStart = 0; while (QueueStart < Queue.size()) { - Module *CurrentModule = Queue[QueueStart++]; + ModuleFile *CurrentModule = Queue[QueueStart++]; // Check whether this module should be skipped. if (Skipped.count(CurrentModule)) @@ -132,16 +133,16 @@ void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), // module that the current module depends on. To indicate this // behavior, we mark all of the reachable modules as having N // incoming edges (which is impossible otherwise). - SmallVector<Module *, 4> Stack; + SmallVector<ModuleFile *, 4> Stack; Stack.push_back(CurrentModule); Skipped.insert(CurrentModule); while (!Stack.empty()) { - Module *NextModule = Stack.back(); + ModuleFile *NextModule = Stack.back(); Stack.pop_back(); // For any module that this module depends on, push it on the // stack (if it hasn't already been marked as visited). - for (llvm::SetVector<Module *>::iterator + for (llvm::SetVector<ModuleFile *>::iterator M = NextModule->Imports.begin(), MEnd = NextModule->Imports.end(); M != MEnd; ++M) { @@ -154,7 +155,7 @@ void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), // For any module that this module depends on, push it on the // stack (if it hasn't already been marked as visited). - for (llvm::SetVector<Module *>::iterator M = CurrentModule->Imports.begin(), + for (llvm::SetVector<ModuleFile *>::iterator M = CurrentModule->Imports.begin(), MEnd = CurrentModule->Imports.end(); M != MEnd; ++M) { @@ -170,17 +171,17 @@ void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), } /// \brief Perform a depth-first visit of the current module. -static bool visitDepthFirst(Module &M, - bool (*Visitor)(Module &M, bool Preorder, +static bool visitDepthFirst(ModuleFile &M, + bool (*Visitor)(ModuleFile &M, bool Preorder, void *UserData), void *UserData, - llvm::SmallPtrSet<Module *, 4> &Visited) { + llvm::SmallPtrSet<ModuleFile *, 4> &Visited) { // Preorder visitation if (Visitor(M, /*Preorder=*/true, UserData)) return true; // Visit children - for (llvm::SetVector<Module *>::iterator IM = M.Imports.begin(), + for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), IMEnd = M.Imports.end(); IM != IMEnd; ++IM) { if (!Visited.insert(*IM)) @@ -194,10 +195,10 @@ static bool visitDepthFirst(Module &M, return Visitor(M, /*Preorder=*/false, UserData); } -void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, +void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, void *UserData), void *UserData) { - llvm::SmallPtrSet<Module *, 4> Visited; + llvm::SmallPtrSet<ModuleFile *, 4> Visited; for (unsigned I = 0, N = Chain.size(); I != N; ++I) { if (!Visited.insert(Chain[I])) continue; @@ -211,8 +212,8 @@ void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, namespace llvm { template<> struct GraphTraits<ModuleManager> { - typedef Module NodeType; - typedef llvm::SetVector<Module *>::const_iterator ChildIteratorType; + typedef ModuleFile NodeType; + typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType; typedef ModuleManager::ModuleConstIterator nodes_iterator; static ChildIteratorType child_begin(NodeType *Node) { @@ -241,7 +242,7 @@ namespace llvm { return true; } - std::string getNodeLabel(Module *M, const ModuleManager&) { + std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { return llvm::sys::path::stem(M->FileName); } }; |