diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp | 1589 |
1 files changed, 1247 insertions, 342 deletions
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); |