diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Serialization/ASTReader.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Serialization/ASTReader.cpp')
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 2238 |
1 files changed, 1341 insertions, 897 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index deba302..d984415 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1,4 +1,4 @@ -//===--- ASTReader.cpp - AST File Reader ------------------------*- C++ -*-===// +//===--- ASTReader.cpp - AST File Reader ----------------------------------===// // // The LLVM Compiler Infrastructure // @@ -12,13 +12,8 @@ //===----------------------------------------------------------------------===// #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/Sema/Sema.h" -#include "clang/Sema/Scope.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" @@ -27,37 +22,42 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Basic/OnDiskHashTable.h" +#include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/FileSystemStatCache.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Basic/VersionTuple.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" +#include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Serialization/GlobalModuleIndex.h" +#include "clang/Serialization/ModuleManager.h" +#include "clang/Serialization/SerializationDiagnostic.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/system_error.h" #include <algorithm> -#include <iterator> #include <cstdio> -#include <sys/stat.h> +#include <iterator> using namespace clang; using namespace clang::serialization; using namespace clang::serialization::reader; +using llvm::BitstreamCursor; //===----------------------------------------------------------------------===// // PCH validator implementation @@ -109,6 +109,14 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return true; } + if (ExistingLangOpts.CommentOpts.BlockCommandNames != + LangOpts.CommentOpts.BlockCommandNames) { + if (Diags) + Diags->Report(diag::err_pch_langopt_value_mismatch) + << "block command names"; + return true; + } + return false; } @@ -440,22 +448,32 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, return Result; } -unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) { - return llvm::HashString(StringRef(a.first, a.second)); +unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) { + return llvm::HashString(a); } std::pair<unsigned, unsigned> -ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) { +ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) { using namespace clang::io; unsigned DataLen = ReadUnalignedLE16(d); unsigned KeyLen = ReadUnalignedLE16(d); return std::make_pair(KeyLen, DataLen); } -std::pair<const char*, unsigned> -ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) { +ASTIdentifierLookupTraitBase::internal_key_type +ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) { assert(n >= 2 && d[n-1] == '\0'); - return std::make_pair((const char*) d, n-1); + return StringRef((const char*) d, n-1); +} + +/// \brief Whether the given identifier is "interesting". +static bool isInterestingIdentifier(IdentifierInfo &II) { + return II.isPoisoned() || + II.isExtensionToken() || + II.getObjCOrBuiltinID() || + II.hasRevertedTokenIDToIdentifier() || + II.hadMacroDefinition() || + II.getFETokenInfo<void>(); } IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, @@ -474,12 +492,17 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // and associate it with the persistent ID. IdentifierInfo *II = KnownII; if (!II) { - II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); + II = &Reader.getIdentifierTable().getOwn(k); KnownII = II; } Reader.SetIdentifierInfo(ID, II); - II->setIsFromAST(); - Reader.markIdentifierUpToDate(II); + if (!II->isFromAST()) { + bool WasInteresting = isInterestingIdentifier(*II); + II->setIsFromAST(); + if (WasInteresting) + II->setChangedSinceDeserialization(); + } + Reader.markIdentifierUpToDate(II); return II; } @@ -493,6 +516,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, Bits >>= 1; bool ExtensionToken = Bits & 0x01; Bits >>= 1; + bool hasSubmoduleMacros = Bits & 0x01; + Bits >>= 1; bool hadMacroDefinition = Bits & 0x01; Bits >>= 1; @@ -503,15 +528,20 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // the new IdentifierInfo. IdentifierInfo *II = KnownII; if (!II) { - II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); + II = &Reader.getIdentifierTable().getOwn(StringRef(k)); KnownII = II; } Reader.markIdentifierUpToDate(II); - II->setIsFromAST(); + if (!II->isFromAST()) { + bool WasInteresting = isInterestingIdentifier(*II); + II->setIsFromAST(); + if (WasInteresting) + II->setChangedSinceDeserialization(); + } // Set or check the various bits in the IdentifierInfo structure. // Token IDs are read-only. - if (HasRevertedTokenIDToIdentifier) + if (HasRevertedTokenIDToIdentifier && II->getTokenID() != tok::identifier) II->RevertTokenIDToIdentifier(); II->setObjCOrBuiltinID(ObjCOrBuiltinID); assert(II->isExtensionToken() == ExtensionToken && @@ -526,13 +556,26 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // If this identifier is a macro, deserialize the macro // definition. if (hadMacroDefinition) { - SmallVector<MacroID, 4> MacroIDs; - while (uint32_t LocalID = ReadUnalignedLE32(d)) { - MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID)); + uint32_t MacroDirectivesOffset = ReadUnalignedLE32(d); + DataLen -= 4; + SmallVector<uint32_t, 8> LocalMacroIDs; + if (hasSubmoduleMacros) { + while (uint32_t LocalMacroID = ReadUnalignedLE32(d)) { + DataLen -= 4; + LocalMacroIDs.push_back(LocalMacroID); + } DataLen -= 4; } - DataLen -= 4; - Reader.setIdentifierIsMacro(II, MacroIDs); + + if (F.Kind == MK_Module) { + for (SmallVectorImpl<uint32_t>::iterator + I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; ++I) { + MacroID MacID = Reader.getGlobalMacroID(F, *I); + Reader.addPendingMacroFromModule(II, &F, MacID, F.DirectImportLoc); + } + } else { + Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset); + } } Reader.SetIdentifierInfo(ID, II); @@ -656,12 +699,13 @@ ASTDeclContextNameLookupTrait::ReadData(internal_key_type, unsigned DataLen) { using namespace clang::io; unsigned NumDecls = ReadUnalignedLE16(d); - LE32DeclID *Start = (LE32DeclID *)d; + LE32DeclID *Start = reinterpret_cast<LE32DeclID *>( + const_cast<unsigned char *>(d)); return std::make_pair(Start, Start + NumDecls); } bool ASTReader::ReadDeclContextStorage(ModuleFile &M, - llvm::BitstreamCursor &Cursor, + BitstreamCursor &Cursor, const std::pair<uint64_t, uint64_t> &Offsets, DeclContextInfo &Info) { SavedStreamPosition SavedPosition(Cursor); @@ -670,17 +714,16 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M, Cursor.JumpToBit(Offsets.first); RecordData Record; - const char *Blob; - unsigned BlobLen; + StringRef Blob; unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); + unsigned RecCode = Cursor.readRecord(Code, Record, &Blob); if (RecCode != DECL_CONTEXT_LEXICAL) { Error("Expected lexical block"); return true; } - Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob); - Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair); + Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob.data()); + Info.NumLexicalDecls = Blob.size() / sizeof(KindDeclIDPair); } // Now the lookup table. @@ -688,18 +731,17 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M, Cursor.JumpToBit(Offsets.second); RecordData Record; - const char *Blob; - unsigned BlobLen; + StringRef Blob; unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); + unsigned RecCode = Cursor.readRecord(Code, Record, &Blob); if (RecCode != DECL_CONTEXT_VISIBLE) { Error("Expected visible lookup table block"); return true; } Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create( - (const unsigned char *)Blob + Record[0], - (const unsigned char *)Blob, + (const unsigned char *)Blob.data() + Record[0], + (const unsigned char *)Blob.data(), ASTDeclContextNameLookupTrait(*this, M)); } @@ -773,7 +815,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F, bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) { using namespace SrcMgr; - llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor; + BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor; // Set the source-location entry cursor to the current position in // the stream. This cursor will be used to read the contents of the @@ -795,35 +837,24 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) { RecordData Record; while (true) { - unsigned Code = SLocEntryCursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (SLocEntryCursor.ReadBlockEnd()) { - Error("error at end of Source Manager block in AST file"); - return true; - } + llvm::BitstreamEntry E = SLocEntryCursor.advanceSkippingSubblocks(); + + switch (E.Kind) { + case llvm::BitstreamEntry::SubBlock: // Handled for us already. + case llvm::BitstreamEntry::Error: + Error("malformed block record in AST file"); + return true; + case llvm::BitstreamEntry::EndBlock: return false; + case llvm::BitstreamEntry::Record: + // The interesting case. + break; } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - SLocEntryCursor.ReadSubBlockID(); - if (SLocEntryCursor.SkipBlock()) { - Error("malformed block record in AST file"); - return true; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - SLocEntryCursor.ReadAbbrevRecord(); - continue; - } - + // Read a record. - const char *BlobStart; - unsigned BlobLen; Record.clear(); - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + StringRef Blob; + switch (SLocEntryCursor.readRecord(E.ID, Record, &Blob)) { default: // Default behavior: ignore. break; @@ -880,22 +911,19 @@ bool ASTReader::ReadSLocEntry(int ID) { ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second; F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]); - llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; + BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; unsigned BaseOffset = F->SLocEntryBaseOffset; ++NumSLocEntriesRead; - unsigned Code = SLocEntryCursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK || - Code == llvm::bitc::ENTER_SUBBLOCK || - Code == llvm::bitc::DEFINE_ABBREV) { + llvm::BitstreamEntry Entry = SLocEntryCursor.advance(); + if (Entry.Kind != llvm::BitstreamEntry::Record) { Error("incorrectly-formatted source location entry in AST file"); return true; } - + RecordData Record; - const char *BlobStart; - unsigned BlobLen; - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + StringRef Blob; + switch (SLocEntryCursor.readRecord(Entry.ID, Record, &Blob)) { default: Error("incorrectly-formatted source location entry in AST file"); return true; @@ -905,10 +933,13 @@ bool ASTReader::ReadSLocEntry(int ID) { // we will also try to fail gracefully by setting up the SLocEntry. unsigned InputID = Record[4]; InputFile IF = getInputFile(*F, InputID); - const FileEntry *File = IF.getPointer(); - bool OverriddenBuffer = IF.getInt(); + const FileEntry *File = IF.getFile(); + bool OverriddenBuffer = IF.isOverridden(); - if (!IF.getPointer()) + // Note that we only check if a File was returned. If it was out-of-date + // we have complained but we will continue creating a FileID to recover + // gracefully. + if (!File) return true; SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); @@ -941,8 +972,7 @@ bool ASTReader::ReadSLocEntry(int ID) { ContentCache->ContentsEntry == ContentCache->OrigEntry) { unsigned Code = SLocEntryCursor.ReadCode(); Record.clear(); - unsigned RecCode - = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); + unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob); if (RecCode != SM_SLOC_BUFFER_BLOB) { Error("AST record has invalid code"); @@ -950,8 +980,7 @@ bool ASTReader::ReadSLocEntry(int ID) { } llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), - File->getName()); + = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), File->getName()); SourceMgr.overrideFileContents(File, Buffer); } @@ -959,15 +988,18 @@ bool ASTReader::ReadSLocEntry(int ID) { } case SM_SLOC_BUFFER_ENTRY: { - const char *Name = BlobStart; + const char *Name = Blob.data(); unsigned Offset = Record[0]; SrcMgr::CharacteristicKind FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); + if (IncludeLoc.isInvalid() && F->Kind == MK_Module) { + IncludeLoc = getImportLocation(F); + } unsigned Code = SLocEntryCursor.ReadCode(); Record.clear(); unsigned RecCode - = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); + = SLocEntryCursor.readRecord(Code, Record, &Blob); if (RecCode != SM_SLOC_BUFFER_BLOB) { Error("AST record has invalid code"); @@ -975,8 +1007,7 @@ bool ASTReader::ReadSLocEntry(int ID) { } llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), - Name); + = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name); SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID, BaseOffset + Offset, IncludeLoc); break; @@ -997,6 +1028,25 @@ bool ASTReader::ReadSLocEntry(int ID) { return false; } +std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) { + if (ID == 0) + return std::make_pair(SourceLocation(), ""); + + if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) { + Error("source location entry ID out-of-range for AST file"); + return std::make_pair(SourceLocation(), ""); + } + + // Find which module file this entry lands in. + ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second; + if (M->Kind != MK_Module) + return std::make_pair(SourceLocation(), ""); + + // FIXME: Can we map this down to a particular submodule? That would be + // ideal. + return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName)); +} + /// \brief Find the location where the module F is imported. SourceLocation ASTReader::getImportLocation(ModuleFile *F) { if (F->ImportLoc.isValid()) @@ -1019,8 +1069,7 @@ SourceLocation ASTReader::getImportLocation(ModuleFile *F) { /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block /// and then leave the cursor pointing into the block. -bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, - unsigned BlockID) { +bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID) { if (Cursor.EnterSubBlock(BlockID)) { Error("malformed block record in AST file"); return Failure; @@ -1039,9 +1088,8 @@ bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, } } -void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset, - MacroInfo *Hint) { - llvm::BitstreamCursor &Stream = F.MacroCursor; +MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { + BitstreamCursor &Stream = F.MacroCursor; // Keep track of where we are in the stream, then jump back there // after reading this macro. @@ -1052,95 +1100,53 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset, SmallVector<IdentifierInfo*, 16> MacroArgs; MacroInfo *Macro = 0; - // RAII object to add the loaded macro information once we're done - // adding tokens. - struct AddLoadedMacroInfoRAII { - Preprocessor &PP; - MacroInfo *Hint; - MacroInfo *MI; - IdentifierInfo *II; - - AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint) - : PP(PP), Hint(Hint), MI(), II() { } - ~AddLoadedMacroInfoRAII( ) { - if (MI) { - // Finally, install the macro. - PP.addLoadedMacroInfo(II, MI, Hint); - } - } - } AddLoadedMacroInfo(PP, Hint); - while (true) { - unsigned Code = Stream.ReadCode(); - switch (Code) { - case llvm::bitc::END_BLOCK: - return; - - case llvm::bitc::ENTER_SUBBLOCK: - // No known subblocks, always skip them. - Stream.ReadSubBlockID(); - if (Stream.SkipBlock()) { - Error("malformed block record in AST file"); - return; - } - continue; - - case llvm::bitc::DEFINE_ABBREV: - Stream.ReadAbbrevRecord(); - continue; - default: break; + // Advance to the next record, but if we get to the end of the block, don't + // pop it (removing all the abbreviations from the cursor) since we want to + // be able to reseek within the block and read entries. + unsigned Flags = BitstreamCursor::AF_DontPopBlockAtEnd; + llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(Flags); + + switch (Entry.Kind) { + case llvm::BitstreamEntry::SubBlock: // Handled for us already. + case llvm::BitstreamEntry::Error: + Error("malformed block record in AST file"); + return Macro; + case llvm::BitstreamEntry::EndBlock: + return Macro; + case llvm::BitstreamEntry::Record: + // The interesting case. + break; } // Read a record. - const char *BlobStart = 0; - unsigned BlobLen = 0; Record.clear(); PreprocessorRecordTypes RecType = - (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart, - BlobLen); + (PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record); switch (RecType) { + case PP_MACRO_DIRECTIVE_HISTORY: + return Macro; + case PP_MACRO_OBJECT_LIKE: case PP_MACRO_FUNCTION_LIKE: { // If we already have a macro, that means that we've hit the end // of the definition of the macro we were looking for. We're // done. if (Macro) - return; + return Macro; - IdentifierInfo *II = getLocalIdentifier(F, Record[0]); - if (II == 0) { - Error("macro must have a name in AST file"); - return; - } - - unsigned GlobalID = getGlobalMacroID(F, Record[1]); - - // If this macro has already been loaded, don't do so again. - if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS]) - return; - - SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]); - unsigned NextIndex = 3; + unsigned NextIndex = 1; // Skip identifier ID. + SubmoduleID SubModID = getGlobalSubmoduleID(F, Record[NextIndex++]); SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex); - MacroInfo *MI = PP.AllocateMacroInfo(Loc); - - // Record this macro. - MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI; - - SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex); - if (UndefLoc.isValid()) - MI->setUndefLoc(UndefLoc); - + MacroInfo *MI = PP.AllocateDeserializedMacroInfo(Loc, SubModID); + MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex)); MI->setIsUsed(Record[NextIndex++]); - MI->setIsFromAST(); - - bool IsPublic = Record[NextIndex++]; - MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex)); if (RecType == PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. bool isC99VarArgs = Record[NextIndex++]; bool isGNUVarArgs = Record[NextIndex++]; + bool hasCommaPasting = Record[NextIndex++]; MacroArgs.clear(); unsigned NumArgs = Record[NextIndex++]; for (unsigned i = 0; i != NumArgs; ++i) @@ -1150,65 +1156,11 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset, MI->setIsFunctionLike(); if (isC99VarArgs) MI->setIsC99Varargs(); if (isGNUVarArgs) MI->setIsGNUVarargs(); + if (hasCommaPasting) MI->setHasCommaPasting(); MI->setArgumentList(MacroArgs.data(), MacroArgs.size(), PP.getPreprocessorAllocator()); } - if (DeserializationListener) - DeserializationListener->MacroRead(GlobalID, MI); - - // If an update record marked this as undefined, do so now. - // FIXME: Only if the submodule this update came from is visible? - MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID); - if (Update != MacroUpdates.end()) { - if (MI->getUndefLoc().isInvalid()) { - for (unsigned I = 0, N = Update->second.size(); I != N; ++I) { - bool Hidden = false; - if (unsigned SubmoduleID = Update->second[I].first) { - if (Module *Owner = getSubmodule(SubmoduleID)) { - if (Owner->NameVisibility == Module::Hidden) { - // Note that this #undef is hidden. - Hidden = true; - - // Record this hiding for later. - HiddenNamesMap[Owner].push_back( - HiddenName(II, MI, Update->second[I].second.UndefLoc)); - } - } - } - - if (!Hidden) { - MI->setUndefLoc(Update->second[I].second.UndefLoc); - if (PPMutationListener *Listener = PP.getPPMutationListener()) - Listener->UndefinedMacro(MI); - break; - } - } - } - MacroUpdates.erase(Update); - } - - // Determine whether this macro definition is visible. - bool Hidden = !MI->isPublic(); - if (!Hidden && GlobalSubmoduleID) { - if (Module *Owner = getSubmodule(GlobalSubmoduleID)) { - if (Owner->NameVisibility == Module::Hidden) { - // The owning module is not visible, and this macro definition - // should not be, either. - Hidden = true; - - // Note that this macro definition was hidden because its owning - // module is not yet visible. - HiddenNamesMap[Owner].push_back(HiddenName(II, MI)); - } - } - } - MI->setHidden(Hidden); - - // Make sure we install the macro once we're done. - AddLoadedMacroInfo.MI = MI; - AddLoadedMacroInfo.II = II; - // Remember that we saw this macro last so that we add the tokens that // form its body to it. Macro = MI; @@ -1219,8 +1171,12 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset, PreprocessedEntityID GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]); PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); - PPRec.RegisterMacroDefinition(Macro, - PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true)); + PreprocessingRecord::PPEntityID + PPID = PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true); + MacroDefinition *PPDef = + cast_or_null<MacroDefinition>(PPRec.getPreprocessedEntity(PPID)); + if (PPDef) + PPRec.RegisterMacroDefinition(Macro, PPDef); } ++NumMacrosRead; @@ -1257,37 +1213,49 @@ ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const return LocalID + I->second; } -unsigned HeaderFileInfoTrait::ComputeHash(const char *path) { - return llvm::HashString(llvm::sys::path::filename(path)); +unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) { + return llvm::hash_combine(ikey.Size, ikey.ModTime); } HeaderFileInfoTrait::internal_key_type -HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; } +HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) { + internal_key_type ikey = { FE->getSize(), FE->getModificationTime(), + FE->getName() }; + return ikey; +} -bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) { - if (strcmp(a, b) == 0) - return true; - - if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b)) +bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) { + if (a.Size != b.Size || a.ModTime != b.ModTime) return false; - // Determine whether the actual files are equivalent. - bool Result = false; - if (llvm::sys::fs::equivalent(a, b, Result)) - return false; + if (strcmp(a.Filename, b.Filename) == 0) + return true; - return Result; + // Determine whether the actual files are equivalent. + FileManager &FileMgr = Reader.getFileManager(); + const FileEntry *FEA = FileMgr.getFile(a.Filename); + const FileEntry *FEB = FileMgr.getFile(b.Filename); + return (FEA && FEA == FEB); } std::pair<unsigned, unsigned> HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) { unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); unsigned DataLen = (unsigned) *d++; - return std::make_pair(KeyLen + 1, DataLen); + return std::make_pair(KeyLen, DataLen); } - + +HeaderFileInfoTrait::internal_key_type +HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { + internal_key_type ikey; + ikey.Size = off_t(clang::io::ReadUnalignedLE64(d)); + ikey.ModTime = time_t(clang::io::ReadUnalignedLE64(d)); + ikey.Filename = (const char *)d; + return ikey; +} + HeaderFileInfoTrait::data_type -HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, +HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, unsigned DataLen) { const unsigned char *End = d + DataLen; using namespace clang::io; @@ -1308,6 +1276,21 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + if (d != End) { + uint32_t LocalSMID = ReadUnalignedLE32(d); + if (LocalSMID) { + // This header is part of a module. Associate it with the module to enable + // implicit module import. + SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID); + Module *Mod = Reader.getSubmodule(GlobalSMID); + HFI.isModuleHeader = true; + FileManager &FileMgr = Reader.getFileManager(); + ModuleMap &ModMap = + Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), /*Excluded=*/false); + } + } + assert(End == d && "Wrong data length in HeaderFileInfo deserialization"); (void)End; @@ -1316,10 +1299,19 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, return HFI; } -void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){ - II->setHadMacroDefinition(true); +void ASTReader::addPendingMacroFromModule(IdentifierInfo *II, + ModuleFile *M, + GlobalMacroID GMacID, + SourceLocation ImportLoc) { assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); - PendingMacroIDs[II].append(IDs.begin(), IDs.end()); + PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, ImportLoc)); +} + +void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II, + ModuleFile *M, + uint64_t MacroDirectivesOffset) { + assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); + PendingMacroIDs[II].push_back(PendingMacroInfo(M, MacroDirectivesOffset)); } void ASTReader::ReadDefinedMacros() { @@ -1328,54 +1320,46 @@ void ASTReader::ReadDefinedMacros() { for (ModuleReverseIterator I = ModuleMgr.rbegin(), E = ModuleMgr.rend(); I != E; ++I) { - llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor; + BitstreamCursor &MacroCursor = (*I)->MacroCursor; // If there was no preprocessor block, skip this file. if (!MacroCursor.getBitStreamReader()) continue; - llvm::BitstreamCursor Cursor = MacroCursor; + BitstreamCursor Cursor = MacroCursor; Cursor.JumpToBit((*I)->MacroStartOffset); RecordData Record; while (true) { - unsigned Code = Cursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) - break; - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - Cursor.ReadSubBlockID(); - if (Cursor.SkipBlock()) { - Error("malformed block record in AST file"); - return; + llvm::BitstreamEntry E = Cursor.advanceSkippingSubblocks(); + + switch (E.Kind) { + case llvm::BitstreamEntry::SubBlock: // Handled for us already. + case llvm::BitstreamEntry::Error: + Error("malformed block record in AST file"); + return; + case llvm::BitstreamEntry::EndBlock: + goto NextCursor; + + case llvm::BitstreamEntry::Record: + Record.clear(); + switch (Cursor.readRecord(E.ID, Record)) { + default: // Default behavior: ignore. + break; + + case PP_MACRO_OBJECT_LIKE: + case PP_MACRO_FUNCTION_LIKE: + getLocalIdentifier(**I, Record[0]); + break; + + case PP_TOKEN: + // Ignore tokens. + break; } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Cursor.ReadAbbrevRecord(); - continue; - } - - // Read a record. - const char *BlobStart; - unsigned BlobLen; - Record.clear(); - switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case PP_MACRO_OBJECT_LIKE: - case PP_MACRO_FUNCTION_LIKE: - getLocalIdentifier(**I, Record[0]); - break; - - case PP_TOKEN: - // Ignore tokens. break; } } + NextCursor: ; } } @@ -1384,10 +1368,20 @@ namespace { class IdentifierLookupVisitor { StringRef Name; unsigned PriorGeneration; + unsigned &NumIdentifierLookups; + unsigned &NumIdentifierLookupHits; IdentifierInfo *Found; + public: - IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration) - : Name(Name), PriorGeneration(PriorGeneration), Found() { } + IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration, + unsigned &NumIdentifierLookups, + unsigned &NumIdentifierLookupHits) + : Name(Name), PriorGeneration(PriorGeneration), + NumIdentifierLookups(NumIdentifierLookups), + NumIdentifierLookupHits(NumIdentifierLookupHits), + Found() + { + } static bool visit(ModuleFile &M, void *UserData) { IdentifierLookupVisitor *This @@ -1396,7 +1390,7 @@ namespace { // 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) @@ -1404,16 +1398,15 @@ namespace { 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); + ++This->NumIdentifierLookups; + ASTIdentifierLookupTable::iterator Pos = IdTable->find(This->Name,&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->NumIdentifierLookupHits; This->Found = *Pos; return true; } @@ -1431,9 +1424,21 @@ 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); + + // If there is a global index, look there first to determine which modules + // provably do not have any results for this identifier. + GlobalModuleIndex::HitSet Hits; + GlobalModuleIndex::HitSet *HitsPtr = 0; + if (!loadGlobalIndex()) { + if (GlobalIndex->lookupIdentifier(II.getName(), Hits)) { + HitsPtr = &Hits; + } + } + + IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration, + NumIdentifierLookups, + NumIdentifierLookupHits); + ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor, HitsPtr); markIdentifierUpToDate(&II); } @@ -1448,27 +1453,196 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { IdentifierGeneration[II] = CurrentGeneration; } -llvm::PointerIntPair<const FileEntry *, 1, bool> -ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { +void ASTReader::resolvePendingMacro(IdentifierInfo *II, + const PendingMacroInfo &PMInfo) { + assert(II); + + if (PMInfo.M->Kind != MK_Module) { + installPCHMacroDirectives(II, *PMInfo.M, + PMInfo.PCHMacroData.MacroDirectivesOffset); + return; + } + + // Module Macro. + + GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID; + SourceLocation ImportLoc = + SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc); + + assert(GMacID); + // If this macro has already been loaded, don't do so again. + if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS]) + return; + + MacroInfo *MI = getMacro(GMacID); + SubmoduleID SubModID = MI->getOwningModuleID(); + MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc, + /*isImported=*/true); + + // Determine whether this macro definition is visible. + bool Hidden = false; + Module *Owner = 0; + if (SubModID) { + if ((Owner = getSubmodule(SubModID))) { + if (Owner->NameVisibility == Module::Hidden) { + // The owning module is not visible, and this macro definition + // should not be, either. + Hidden = true; + + // Note that this macro definition was hidden because its owning + // module is not yet visible. + HiddenNamesMap[Owner].push_back(HiddenName(II, MD)); + } + } + } + + if (!Hidden) + installImportedMacro(II, MD, Owner); +} + +void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, + ModuleFile &M, uint64_t Offset) { + assert(M.Kind != MK_Module); + + BitstreamCursor &Cursor = M.MacroCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(Offset); + + llvm::BitstreamEntry Entry = + Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); + if (Entry.Kind != llvm::BitstreamEntry::Record) { + Error("malformed block record in AST file"); + return; + } + + RecordData Record; + PreprocessorRecordTypes RecType = + (PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record); + if (RecType != PP_MACRO_DIRECTIVE_HISTORY) { + Error("malformed block record in AST file"); + return; + } + + // Deserialize the macro directives history in reverse source-order. + MacroDirective *Latest = 0, *Earliest = 0; + unsigned Idx = 0, N = Record.size(); + while (Idx < N) { + MacroDirective *MD = 0; + SourceLocation Loc = ReadSourceLocation(M, Record, Idx); + MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++]; + switch (K) { + case MacroDirective::MD_Define: { + GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]); + MacroInfo *MI = getMacro(GMacID); + bool isImported = Record[Idx++]; + bool isAmbiguous = Record[Idx++]; + DefMacroDirective *DefMD = + PP.AllocateDefMacroDirective(MI, Loc, isImported); + DefMD->setAmbiguous(isAmbiguous); + MD = DefMD; + break; + } + case MacroDirective::MD_Undefine: + MD = PP.AllocateUndefMacroDirective(Loc); + break; + case MacroDirective::MD_Visibility: { + bool isPublic = Record[Idx++]; + MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic); + break; + } + } + + if (!Latest) + Latest = MD; + if (Earliest) + Earliest->setPrevious(MD); + Earliest = MD; + } + + PP.setLoadedMacroDirective(II, Latest); +} + +/// \brief For the given macro definitions, check if they are both in system +/// modules and if one of the two is in the clang builtin headers. +static bool isSystemAndClangMacro(MacroInfo *PrevMI, MacroInfo *NewMI, + Module *NewOwner, ASTReader &Reader) { + assert(PrevMI && NewMI); + if (!NewOwner) + return false; + Module *PrevOwner = 0; + if (SubmoduleID PrevModID = PrevMI->getOwningModuleID()) + PrevOwner = Reader.getSubmodule(PrevModID); + if (!PrevOwner) + return false; + if (PrevOwner == NewOwner) + return false; + if (!PrevOwner->IsSystem || !NewOwner->IsSystem) + return false; + + SourceManager &SM = Reader.getSourceManager(); + FileID PrevFID = SM.getFileID(PrevMI->getDefinitionLoc()); + FileID NewFID = SM.getFileID(NewMI->getDefinitionLoc()); + const FileEntry *PrevFE = SM.getFileEntryForID(PrevFID); + const FileEntry *NewFE = SM.getFileEntryForID(NewFID); + if (PrevFE == 0 || NewFE == 0) + return false; + + Preprocessor &PP = Reader.getPreprocessor(); + ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); + const DirectoryEntry *BuiltinDir = ModMap.getBuiltinIncludeDir(); + + return (PrevFE->getDir() == BuiltinDir) != (NewFE->getDir() == BuiltinDir); +} + +void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD, + Module *Owner) { + assert(II && MD); + + DefMacroDirective *DefMD = cast<DefMacroDirective>(MD); + MacroDirective *Prev = PP.getMacroDirective(II); + if (Prev) { + MacroDirective::DefInfo PrevDef = Prev->getDefinition(); + MacroInfo *PrevMI = PrevDef.getMacroInfo(); + MacroInfo *NewMI = DefMD->getInfo(); + if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP, + /*Syntactically=*/true)) { + // Before marking the macros as ambiguous, check if this is a case where + // the system macro uses a not identical definition compared to a macro + // from the clang headers. For example: + // #define LONG_MAX __LONG_MAX__ (clang's limits.h) + // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) + // in which case don't mark them to avoid the "ambiguous macro expansion" + // warning. + // FIXME: This should go away if the system headers get "fixed" to use + // identical definitions. + if (!isSystemAndClangMacro(PrevMI, NewMI, Owner, *this)) { + PrevDef.getDirective()->setAmbiguous(true); + DefMD->setAmbiguous(true); + } + } + } + + PP.appendMacroDirective(II, MD); +} + +InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { // If this ID is bogus, just return an empty input file. if (ID == 0 || ID > F.InputFilesLoaded.size()) return InputFile(); // If we've already loaded this input file, return it. - if (F.InputFilesLoaded[ID-1].getPointer()) + if (F.InputFilesLoaded[ID-1].getFile()) return F.InputFilesLoaded[ID-1]; // Go find this input file. - llvm::BitstreamCursor &Cursor = F.InputFilesCursor; + BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(F.InputFileOffsets[ID-1]); unsigned Code = Cursor.ReadCode(); RecordData Record; - const char *BlobStart = 0; - unsigned BlobLen = 0; - switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record, - &BlobStart, &BlobLen)) { + StringRef Blob; + switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { case INPUT_FILE: { unsigned StoredID = Record[0]; assert(ID == StoredID && "Bogus stored ID or offset"); @@ -1478,7 +1652,7 @@ ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { bool Overridden = (bool)Record[3]; // Get the file entry for this input file. - StringRef OrigFilename(BlobStart, BlobLen); + StringRef OrigFilename = Blob; std::string Filename = OrigFilename; MaybeAddSystemRootToFilename(F, Filename); const FileEntry *File @@ -1511,17 +1685,15 @@ ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { } return InputFile(); } - - // Note that we've loaded this input file. - F.InputFilesLoaded[ID-1] = InputFile(File, Overridden); - + // Check if there was a request to override the contents of the file // that was part of the precompiled header. Overridding such a file // can lead to problems when lexing using the source locations from the // PCH. SourceManager &SM = getSourceManager(); if (!Overridden && SM.isFileOverridden(File)) { - Error(diag::err_fe_pch_file_overridden, Filename); + if (Complain) + Error(diag::err_fe_pch_file_overridden, Filename); // After emitting the diagnostic, recover by disabling the override so // that the original file will be used. SM.disableFileContentsOverride(File); @@ -1532,33 +1704,29 @@ ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { StoredSize, StoredTime); } - // For an overridden file, there is nothing to validate. - if (Overridden) - return InputFile(File, Overridden); - - // The stat info from the FileEntry came from the cached stat - // info of the PCH, so we cannot trust it. - struct stat StatBuf; - if (::stat(File->getName(), &StatBuf) != 0) { - StatBuf.st_size = File->getSize(); - StatBuf.st_mtime = File->getModificationTime(); - } + bool IsOutOfDate = false; - if ((StoredSize != StatBuf.st_size + // For an overridden file, there is nothing to validate. + if (!Overridden && (StoredSize != File->getSize() #if !defined(LLVM_ON_WIN32) // In our regression testing, the Windows file system seems to // have inconsistent modification times that sometimes // erroneously trigger this error-handling path. - || StoredTime != StatBuf.st_mtime + || StoredTime != File->getModificationTime() #endif )) { - if (Complain) - Error(diag::err_fe_pch_file_modified, Filename); - - return InputFile(); + if (Complain) { + Error(diag::err_fe_pch_file_modified, Filename, F.FileName); + } + + IsOutOfDate = true; } - return InputFile(File, Overridden); + InputFile IF = InputFile(File, Overridden, IsOutOfDate); + + // Note that we've loaded this input file. + F.InputFilesLoaded[ID-1] = IF; + return IF; } } @@ -1609,9 +1777,9 @@ void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, - llvm::SmallVectorImpl<ModuleFile *> &Loaded, + SmallVectorImpl<ImportedModule> &Loaded, unsigned ClientLoadCapabilities) { - llvm::BitstreamCursor &Stream = F.Stream; + BitstreamCursor &Stream = F.Stream; if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) { Error("malformed block record in AST file"); @@ -1620,27 +1788,29 @@ ASTReader::ReadControlBlock(ModuleFile &F, // Read all of the records and blocks in the control block. RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Error("error at end of control block in AST file"); - return Failure; - } - - // Validate all of the input files. + while (1) { + llvm::BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + case llvm::BitstreamEntry::Error: + Error("malformed block record in AST file"); + return Failure; + case llvm::BitstreamEntry::EndBlock: + // Validate all of the non-system input files. if (!DisableValidation) { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; - for (unsigned I = 0, N = Record[0]; I < N; ++I) - if (!getInputFile(F, I+1, Complain).getPointer()) + // All user input files reside at the index range [0, Record[1]). + // Record is the one from INPUT_FILE_OFFSETS. + for (unsigned I = 0, N = Record[1]; I < N; ++I) { + InputFile IF = getInputFile(F, I+1, Complain); + if (!IF.getFile() || IF.isOutOfDate()) return OutOfDate; + } } - return Success; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - switch (Stream.ReadSubBlockID()) { + + case llvm::BitstreamEntry::SubBlock: + switch (Entry.ID) { case INPUT_FILES_BLOCK_ID: F.InputFilesCursor = Stream; if (Stream.SkipBlock() || // Skip with the main cursor @@ -1650,28 +1820,24 @@ ASTReader::ReadControlBlock(ModuleFile &F, return Failure; } continue; - + default: - if (!Stream.SkipBlock()) - continue; - break; + if (Stream.SkipBlock()) { + Error("malformed block record in AST file"); + return Failure; + } + continue; } - - Error("malformed block record in AST file"); - return Failure; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; + + case llvm::BitstreamEntry::Record: + // The interesting case. + break; } // Read and process a record. Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record, - &BlobStart, &BlobLen)) { + StringRef Blob; + switch ((ControlRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) { case METADATA: { if (Record[0] != VERSION_MAJOR && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) @@ -1689,7 +1855,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.RelocatablePCH = Record[4]; const std::string &CurBranch = getClangFullRepositoryVersion(); - StringRef ASTBranch(BlobStart, BlobLen); + StringRef ASTBranch = Blob; if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch; @@ -1704,16 +1870,25 @@ ASTReader::ReadControlBlock(ModuleFile &F, while (Idx < N) { // Read information about the AST file. ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; + // The import location will be the local one for now; we will adjust + // all import locations of module imports after the global source + // location info are setup. + SourceLocation ImportLoc = + SourceLocation::getFromRawEncoding(Record[Idx++]); + off_t StoredSize = (off_t)Record[Idx++]; + time_t StoredModTime = (time_t)Record[Idx++]; unsigned Length = Record[Idx++]; SmallString<128> ImportedFile(Record.begin() + Idx, Record.begin() + Idx + Length); Idx += Length; // Load the AST file. - switch(ReadASTCore(ImportedFile, ImportedKind, &F, Loaded, + switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded, + StoredSize, StoredModTime, ClientLoadCapabilities)) { case Failure: return Failure; // If we have to ignore the dependency, we'll have to ignore this too. + case Missing: case OutOfDate: return OutOfDate; case VersionMismatch: return VersionMismatch; case ConfigurationMismatch: return ConfigurationMismatch; @@ -1781,28 +1956,29 @@ ASTReader::ReadControlBlock(ModuleFile &F, case ORIGINAL_FILE: F.OriginalSourceFileID = FileID::get(Record[0]); - F.ActualOriginalSourceFileName.assign(BlobStart, BlobLen); + F.ActualOriginalSourceFileName = Blob; F.OriginalSourceFileName = F.ActualOriginalSourceFileName; MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName); break; + case ORIGINAL_FILE_ID: + F.OriginalSourceFileID = FileID::get(Record[0]); + break; + case ORIGINAL_PCH_DIR: - F.OriginalDir.assign(BlobStart, BlobLen); + F.OriginalDir = Blob; break; case INPUT_FILE_OFFSETS: - F.InputFileOffsets = (const uint32_t *)BlobStart; + F.InputFileOffsets = (const uint32_t *)Blob.data(); F.InputFilesLoaded.resize(Record[0]); break; } } - - Error("premature end of bitstream in AST file"); - return Failure; } bool ASTReader::ReadASTBlock(ModuleFile &F) { - llvm::BitstreamCursor &Stream = F.Stream; + BitstreamCursor &Stream = F.Stream; if (Stream.EnterSubBlock(AST_BLOCK_ID)) { Error("malformed block record in AST file"); @@ -1811,23 +1987,28 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // Read all of the records and blocks for the AST file. RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Error("error at end of module block in AST file"); - return true; - } - + while (1) { + llvm::BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + case llvm::BitstreamEntry::Error: + Error("error at end of module block in AST file"); + return true; + case llvm::BitstreamEntry::EndBlock: { + // Outside of C++, we do not store a lookup map for the translation unit. + // Instead, mark it as needing a lookup map to be built if this module + // contains any declarations lexically within it (which it always does!). + // This usually has no cost, since we very rarely need the lookup map for + // the translation unit outside C++. DeclContext *DC = Context.getTranslationUnitDecl(); - if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage()) + if (DC->hasExternalLexicalStorage() && + !getContext().getLangOpts().CPlusPlus) DC->setMustBuildLookupTable(); - + return false; } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - switch (Stream.ReadSubBlockID()) { + case llvm::BitstreamEntry::SubBlock: + switch (Entry.ID) { case DECLTYPES_BLOCK_ID: // We lazily load the decls block, but we want to set up the // DeclsCursor cursor to point into it. Clone our current bitcode @@ -1841,19 +2022,19 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { return true; } break; - + case DECL_UPDATES_BLOCK_ID: if (Stream.SkipBlock()) { Error("malformed block record in AST file"); return true; } break; - + case PREPROCESSOR_BLOCK_ID: F.MacroCursor = Stream; if (!PP.getExternalSource()) PP.setExternalSource(this); - + if (Stream.SkipBlock() || ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) { Error("malformed block record in AST file"); @@ -1861,20 +2042,20 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo(); break; - + case PREPROCESSOR_DETAIL_BLOCK_ID: F.PreprocessorDetailCursor = Stream; if (Stream.SkipBlock() || - ReadBlockAbbrevs(F.PreprocessorDetailCursor, + ReadBlockAbbrevs(F.PreprocessorDetailCursor, PREPROCESSOR_DETAIL_BLOCK_ID)) { - Error("malformed preprocessor detail record in AST file"); - return true; - } + Error("malformed preprocessor detail record in AST file"); + return true; + } F.PreprocessorDetailStartOffset - = F.PreprocessorDetailCursor.GetCurrentBitNo(); - + = F.PreprocessorDetailCursor.GetCurrentBitNo(); + if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(/*RecordConditionalDirectives=*/false); + PP.createPreprocessingRecord(); if (!PP.getPreprocessingRecord()->getExternalSource()) PP.getPreprocessingRecord()->SetExternalSource(*this); break; @@ -1883,14 +2064,14 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { if (ReadSourceManagerBlock(F)) return true; break; - + case SUBMODULE_BLOCK_ID: if (ReadSubmoduleBlock(F)) return true; break; - + case COMMENTS_BLOCK_ID: { - llvm::BitstreamCursor C = Stream; + BitstreamCursor C = Stream; if (Stream.SkipBlock() || ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) { Error("malformed comments block in AST file"); @@ -1899,27 +2080,25 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { CommentsCursors.push_back(std::make_pair(C, &F)); break; } - + default: - if (!Stream.SkipBlock()) - break; - Error("malformed block record in AST file"); - return true; + if (Stream.SkipBlock()) { + Error("malformed block record in AST file"); + return true; + } + break; } continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; + + case llvm::BitstreamEntry::Record: + // The interesting case. + break; } // Read and process a record. Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record, - &BlobStart, &BlobLen)) { + StringRef Blob; + switch ((ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) { default: // Default behavior: ignore. break; @@ -1928,7 +2107,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { Error("duplicate TYPE_OFFSET record in AST file"); return true; } - F.TypeOffsets = (const uint32_t *)BlobStart; + F.TypeOffsets = (const uint32_t *)Blob.data(); F.LocalNumTypes = Record[0]; unsigned LocalBaseTypeIndex = Record[1]; F.BaseTypeIndex = getTotalNumTypes(); @@ -1952,7 +2131,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { Error("duplicate DECL_OFFSET record in AST file"); return true; } - F.DeclOffsets = (const DeclOffset *)BlobStart; + F.DeclOffsets = (const DeclOffset *)Blob.data(); F.LocalNumDecls = Record[0]; unsigned LocalBaseDeclID = Record[1]; F.BaseDeclID = getTotalNumDecls(); @@ -1980,9 +2159,9 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case TU_UPDATE_LEXICAL: { DeclContext *TU = Context.getTranslationUnitDecl(); DeclContextInfo &Info = F.DeclContextInfos[TU]; - Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(BlobStart); + Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(Blob.data()); Info.NumLexicalDecls - = static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair)); + = static_cast<unsigned int>(Blob.size() / sizeof(KindDeclIDPair)); TU->setHasExternalLexicalStorage(true); break; } @@ -1992,8 +2171,8 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { serialization::DeclID ID = ReadDeclID(F, Record, Idx); ASTDeclContextNameLookupTable *Table = ASTDeclContextNameLookupTable::Create( - (const unsigned char *)BlobStart + Record[Idx++], - (const unsigned char *)BlobStart, + (const unsigned char *)Blob.data() + Record[Idx++], + (const unsigned char *)Blob.data(), ASTDeclContextNameLookupTrait(*this, F)); if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU? DeclContext *TU = Context.getTranslationUnitDecl(); @@ -2005,7 +2184,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } case IDENTIFIER_TABLE: - F.IdentifierTableData = BlobStart; + F.IdentifierTableData = Blob.data(); if (Record[0]) { F.IdentifierLookupTable = ASTIdentifierLookupTable::Create( @@ -2022,7 +2201,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { Error("duplicate IDENTIFIER_OFFSET record in AST file"); return true; } - F.IdentifierOffsets = (const uint32_t *)BlobStart; + F.IdentifierOffsets = (const uint32_t *)Blob.data(); F.LocalNumIdentifiers = Record[0]; unsigned LocalBaseIdentifierID = Record[1]; F.BaseIdentifierID = getTotalNumIdentifiers(); @@ -2051,8 +2230,24 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; case SPECIAL_TYPES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - SpecialTypes.push_back(getGlobalTypeID(F, Record[I])); + if (SpecialTypes.empty()) { + for (unsigned I = 0, N = Record.size(); I != N; ++I) + SpecialTypes.push_back(getGlobalTypeID(F, Record[I])); + break; + } + + if (SpecialTypes.size() != Record.size()) { + Error("invalid special-types record"); + return true; + } + + for (unsigned I = 0, N = Record.size(); I != N; ++I) { + serialization::TypeID ID = getGlobalTypeID(F, Record[I]); + if (!SpecialTypes[I]) + SpecialTypes[I] = ID; + // FIXME: If ID && SpecialTypes[I] != ID, do we need a separate + // merge step? + } break; case STATISTICS: @@ -2094,13 +2289,13 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } break; - case LOCALLY_SCOPED_EXTERNAL_DECLS: + case LOCALLY_SCOPED_EXTERN_C_DECLS: for (unsigned I = 0, N = Record.size(); I != N; ++I) - LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I])); + LocallyScopedExternCDecls.push_back(getGlobalDeclID(F, Record[I])); break; case SELECTOR_OFFSETS: { - F.SelectorOffsets = (const uint32_t *)BlobStart; + F.SelectorOffsets = (const uint32_t *)Blob.data(); F.LocalNumSelectors = Record[0]; unsigned LocalBaseSelectorID = Record[1]; F.BaseSelectorID = getTotalNumSelectors(); @@ -2122,7 +2317,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } case METHOD_POOL: - F.SelectorLookupTableData = (const unsigned char *)BlobStart; + F.SelectorLookupTableData = (const unsigned char *)Blob.data(); if (Record[0]) F.SelectorLookupTable = ASTSelectorLookupTable::Create( @@ -2149,12 +2344,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; case FILE_SORTED_DECLS: - F.FileSortedDecls = (const DeclID *)BlobStart; + F.FileSortedDecls = (const DeclID *)Blob.data(); F.NumFileSortedDecls = Record[0]; break; case SOURCE_LOCATION_OFFSETS: { - F.SLocEntryOffsets = (const uint32_t *)BlobStart; + F.SLocEntryOffsets = (const uint32_t *)Blob.data(); F.LocalNumSLocEntries = Record[0]; unsigned SLocSpaceSize = Record[1]; llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = @@ -2187,8 +2382,8 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { case MODULE_OFFSET_MAP: { // Additional remapping information. - const unsigned char *Data = (const unsigned char*)BlobStart; - const unsigned char *DataEnd = Data + BlobLen; + const unsigned char *Data = (const unsigned char*)Blob.data(); + const unsigned char *DataEnd = Data + Blob.size(); // Continuous range maps we may be updating in our module. ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap); @@ -2324,15 +2519,15 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; case PPD_ENTITIES_OFFSETS: { - F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart; - assert(BlobLen % sizeof(PPEntityOffset) == 0); - F.NumPreprocessedEntities = BlobLen / sizeof(PPEntityOffset); + F.PreprocessedEntityOffsets = (const PPEntityOffset *)Blob.data(); + assert(Blob.size() % sizeof(PPEntityOffset) == 0); + F.NumPreprocessedEntities = Blob.size() / sizeof(PPEntityOffset); unsigned LocalBasePreprocessedEntityID = Record[0]; unsigned StartingID; if (!PP.getPreprocessingRecord()) - PP.createPreprocessingRecord(/*RecordConditionalDirectives=*/false); + PP.createPreprocessingRecord(); if (!PP.getPreprocessingRecord()->getExternalSource()) PP.getPreprocessingRecord()->SetExternalSource(*this); StartingID @@ -2384,7 +2579,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } F.LocalNumObjCCategoriesInMap = Record[0]; - F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart; + F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)Blob.data(); break; } @@ -2399,7 +2594,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } F.LocalNumCXXBaseSpecifiers = Record[0]; - F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart; + F.CXXBaseSpecifiersOffsets = (const uint32_t *)Blob.data(); NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers; break; } @@ -2421,9 +2616,8 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; case HEADER_SEARCH_TABLE: { - F.HeaderFileInfoTableData = BlobStart; + F.HeaderFileInfoTableData = Blob.data(); F.LocalNumHeaderFileInfos = Record[1]; - F.HeaderFileFrameworkStrings = BlobStart + Record[2]; if (Record[0]) { F.HeaderFileInfoTable = HeaderFileInfoLookupTable::Create( @@ -2431,7 +2625,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { (const unsigned char *)F.HeaderFileInfoTableData, HeaderFileInfoTrait(*this, F, &PP.getHeaderSearchInfo(), - BlobStart + Record[2])); + Blob.data() + Record[2])); PP.getHeaderSearchInfo().SetExternalSource(this); if (!PP.getHeaderSearchInfo().getExternalLookup()) @@ -2459,7 +2653,24 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { for (unsigned I = 0, N = Record.size(); I != N; ++I) KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); break; - + + case UNDEFINED_BUT_USED: + if (UndefinedButUsed.size() % 2 != 0) { + Error("Invalid existing UndefinedButUsed"); + return true; + } + + if (Record.size() % 2 != 0) { + Error("invalid undefined-but-used record"); + return true; + } + for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { + UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++])); + UndefinedButUsed.push_back( + ReadSourceLocation(F, Record, I).getRawEncoding()); + } + break; + case IMPORTED_MODULES: { if (F.Kind != MK_Module) { // If we aren't loading a module (which has its own exports), make @@ -2485,7 +2696,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } F.LocalNumRedeclarationsInMap = Record[0]; - F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart; + F.RedeclarationsMap = (const LocalRedeclarationsInfo *)Blob.data(); break; } @@ -2504,7 +2715,7 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { Error("duplicate MACRO_OFFSET record in AST file"); return true; } - F.MacroOffsets = (const uint32_t *)BlobStart; + F.MacroOffsets = (const uint32_t *)Blob.data(); F.LocalNumMacros = Record[0]; unsigned LocalBaseMacroID = Record[1]; F.BaseMacroID = getTotalNumMacros(); @@ -2523,60 +2734,73 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; } - case MACRO_UPDATES: { - for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - MacroID ID = getGlobalMacroID(F, Record[I++]); - if (I == N) - break; - - SourceLocation UndefLoc = ReadSourceLocation(F, Record, I); - SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);; - MacroUpdate Update; - Update.UndefLoc = UndefLoc; - MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update)); - } + case MACRO_TABLE: { + // FIXME: Not used yet. break; } } } - Error("premature end of bitstream in AST file"); - return true; } -void ASTReader::makeNamesVisible(const HiddenNames &Names) { - for (unsigned I = 0, N = Names.size(); I != N; ++I) { - switch (Names[I].getKind()) { - case HiddenName::Declaration: - Names[I].getDecl()->Hidden = false; - break; +/// \brief Move the given method to the back of the global list of methods. +static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { + // Find the entry for this selector in the method pool. + Sema::GlobalMethodPool::iterator Known + = S.MethodPool.find(Method->getSelector()); + if (Known == S.MethodPool.end()) + return; - case HiddenName::MacroVisibility: { - std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro(); - Macro.second->setHidden(!Macro.second->isPublic()); - if (Macro.second->isDefined()) { - PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second); + // Retrieve the appropriate method list. + ObjCMethodList &Start = Method->isInstanceMethod()? Known->second.first + : Known->second.second; + bool Found = false; + for (ObjCMethodList *List = &Start; List; List = List->Next) { + if (!Found) { + if (List->Method == Method) { + Found = true; + } else { + // Keep searching. + continue; } - break; } - case HiddenName::MacroUndef: { - std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro(); - if (Macro.second->isDefined()) { - Macro.second->setUndefLoc(Names[I].getMacroUndefLoc()); - if (PPMutationListener *Listener = PP.getPPMutationListener()) - Listener->UndefinedMacro(Macro.second); - PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second); + if (List->Next) + List->Method = List->Next->Method; + else + List->Method = Method; + } +} + +void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) { + for (unsigned I = 0, N = Names.size(); I != N; ++I) { + switch (Names[I].getKind()) { + case HiddenName::Declaration: { + Decl *D = Names[I].getDecl(); + bool wasHidden = D->Hidden; + D->Hidden = false; + + if (wasHidden && SemaObj) { + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { + moveMethodToBackOfGlobalList(*SemaObj, Method); + } } break; } + case HiddenName::MacroVisibility: { + std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro(); + installImportedMacro(Macro.first, Macro.second, Owner); + break; + } } } } void ASTReader::makeModuleVisible(Module *Mod, - Module::NameVisibilityKind NameVisibility) { + Module::NameVisibilityKind NameVisibility, + SourceLocation ImportLoc, + bool Complain) { llvm::SmallPtrSet<Module *, 4> Visited; - llvm::SmallVector<Module *, 4> Stack; + SmallVector<Module *, 4> Stack; Stack.push_back(Mod); while (!Stack.empty()) { Mod = Stack.back(); @@ -2600,7 +2824,7 @@ void ASTReader::makeModuleVisible(Module *Mod, // mark them as visible. HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod); if (Hidden != HiddenNamesMap.end()) { - makeNamesVisible(Hidden->second); + makeNamesVisible(Hidden->second, Hidden->first); HiddenNamesMap.erase(Hidden); } @@ -2614,80 +2838,86 @@ void ASTReader::makeModuleVisible(Module *Mod, } // 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; - } - - // 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.insert(Imported)) - continue; - - 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; - } + SmallVector<Module *, 16> Exports; + Mod->getExportedModules(Exports); + for (SmallVectorImpl<Module *>::iterator + I = Exports.begin(), E = Exports.end(); I != E; ++I) { + Module *Exported = *I; + if (Visited.insert(Exported)) + Stack.push_back(Exported); + } + + // Detect any conflicts. + if (Complain) { + assert(ImportLoc.isValid() && "Missing import location"); + for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) { + if (Mod->Conflicts[I].Other->NameVisibility >= NameVisibility) { + Diag(ImportLoc, diag::warn_module_conflict) + << Mod->getFullModuleName() + << Mod->Conflicts[I].Other->getFullModuleName() + << Mod->Conflicts[I].Message; + // FIXME: Need note where the other module was imported. } } - - if (!Acceptable) - continue; - - Stack.push_back(Imported); } } } +bool ASTReader::loadGlobalIndex() { + if (GlobalIndex) + return false; + + if (TriedLoadingGlobalIndex || !UseGlobalIndex || + !Context.getLangOpts().Modules) + return true; + + // Try to load the global index. + TriedLoadingGlobalIndex = true; + StringRef ModuleCachePath + = getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); + std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> Result + = GlobalModuleIndex::readIndex(ModuleCachePath); + if (!Result.first) + return true; + + GlobalIndex.reset(Result.first); + ModuleMgr.setGlobalIndex(GlobalIndex.get()); + return false; +} + +bool ASTReader::isGlobalIndexUnavailable() const { + return Context.getLangOpts().Modules && UseGlobalIndex && + !hasGlobalIndex() && TriedLoadingGlobalIndex; +} + ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type, + SourceLocation ImportLoc, unsigned ClientLoadCapabilities) { // Bump the generation number. unsigned PreviousGeneration = CurrentGeneration++; unsigned NumModules = ModuleMgr.size(); - llvm::SmallVector<ModuleFile *, 4> Loaded; - switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, + SmallVector<ImportedModule, 4> Loaded; + switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc, /*ImportedBy=*/0, Loaded, + 0, 0, ClientLoadCapabilities)) { case Failure: + case Missing: case OutOfDate: case VersionMismatch: case ConfigurationMismatch: case HadErrors: - ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end()); + ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end(), + Context.getLangOpts().Modules + ? &PP.getHeaderSearchInfo().getModuleMap() + : 0); + + // If we find that any modules are unusable, the global index is going + // to be out-of-date. Just remove it. + GlobalIndex.reset(); + ModuleMgr.setGlobalIndex(0); return ReadResult; case Success: @@ -2697,10 +2927,10 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, // Here comes stuff that we only do once the entire chain is loaded. // Load the AST blocks of all of the modules that we loaded. - for (llvm::SmallVectorImpl<ModuleFile *>::iterator M = Loaded.begin(), - MEnd = Loaded.end(); + for (SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(), + MEnd = Loaded.end(); M != MEnd; ++M) { - ModuleFile &F = **M; + ModuleFile &F = *M->Mod; // Read the AST block. if (ReadASTBlock(F)) @@ -2723,6 +2953,24 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, } } + // Setup the import locations and notify the module manager that we've + // committed to these module files. + for (SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(), + MEnd = Loaded.end(); + M != MEnd; ++M) { + ModuleFile &F = *M->Mod; + + ModuleMgr.moduleFileAccepted(&F); + + // Set the import location. + F.DirectImportLoc = ImportLoc; + if (!M->ImportedBy) + F.ImportLoc = M->ImportLoc; + else + F.ImportLoc = ReadSourceLocation(*M->ImportedBy, + M->ImportLoc.getRawEncoding()); + } + // 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. @@ -2732,22 +2980,34 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, Id->second->setOutOfDate(true); // Resolve any unresolved module exports. - for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) { - UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I]; + for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) { + UnresolvedModuleRef &Unresolved = UnresolvedModuleRefs[I]; SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID); Module *ResolvedMod = getSubmodule(GlobalID); - - if (Unresolved.IsImport) { + + switch (Unresolved.Kind) { + case UnresolvedModuleRef::Conflict: + if (ResolvedMod) { + Module::Conflict Conflict; + Conflict.Other = ResolvedMod; + Conflict.Message = Unresolved.String.str(); + Unresolved.Mod->Conflicts.push_back(Conflict); + } + continue; + + case UnresolvedModuleRef::Import: if (ResolvedMod) Unresolved.Mod->Imports.push_back(ResolvedMod); continue; - } - if (ResolvedMod || Unresolved.IsWildcard) - Unresolved.Mod->Exports.push_back( - Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard)); + case UnresolvedModuleRef::Export: + if (ResolvedMod || Unresolved.IsWildcard) + Unresolved.Mod->Exports.push_back( + Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard)); + continue; + } } - UnresolvedModuleImportExports.clear(); + UnresolvedModuleRefs.clear(); InitializeContext(); @@ -2777,35 +3037,64 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ObjCClassesLoaded[I], PreviousGeneration); } - + return Success; } ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, + SourceLocation ImportLoc, ModuleFile *ImportedBy, - llvm::SmallVectorImpl<ModuleFile *> &Loaded, + SmallVectorImpl<ImportedModule> &Loaded, + off_t ExpectedSize, time_t ExpectedModTime, unsigned ClientLoadCapabilities) { ModuleFile *M; - bool NewModule; std::string ErrorStr; - llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy, - CurrentGeneration, ErrorStr); - - if (!M) { - // We couldn't load the module. - std::string Msg = "Unable to load module \"" + FileName.str() + "\": " - + ErrorStr; - Error(Msg); - return Failure; - } + ModuleManager::AddModuleResult AddResult + = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, + CurrentGeneration, ExpectedSize, ExpectedModTime, + M, ErrorStr); - if (!NewModule) { - // We've already loaded this module. + switch (AddResult) { + case ModuleManager::AlreadyLoaded: return Success; + + case ModuleManager::NewlyLoaded: + // Load module file below. + break; + + case ModuleManager::Missing: + // The module file was missing; if the client handle handle, that, return + // it. + if (ClientLoadCapabilities & ARR_Missing) + return Missing; + + // Otherwise, return an error. + { + std::string Msg = "Unable to load module \"" + FileName.str() + "\": " + + ErrorStr; + Error(Msg); + } + return Failure; + + case ModuleManager::OutOfDate: + // We couldn't load the module file because it is out-of-date. If the + // client can handle out-of-date, return it. + if (ClientLoadCapabilities & ARR_OutOfDate) + return OutOfDate; + + // Otherwise, return an error. + { + std::string Msg = "Unable to load module \"" + FileName.str() + "\": " + + ErrorStr; + Error(Msg); + } + return Failure; } + assert(M && "Missing module file"); + // FIXME: This seems rather a hack. Should CurrentDir be part of the // module? if (FileName != "-") { @@ -2814,7 +3103,7 @@ ASTReader::ReadASTCore(StringRef FileName, } ModuleFile &F = *M; - llvm::BitstreamCursor &Stream = F.Stream; + BitstreamCursor &Stream = F.Stream; Stream.init(F.StreamFile); F.SizeInBits = F.Buffer->getBufferSize() * 8; @@ -2827,18 +3116,25 @@ ASTReader::ReadASTCore(StringRef FileName, return Failure; } - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); + // This is used for compatibility with older PCH formats. + bool HaveReadControlBlock = false; - if (Code != llvm::bitc::ENTER_SUBBLOCK) { + while (1) { + llvm::BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + case llvm::BitstreamEntry::Error: + case llvm::BitstreamEntry::EndBlock: + case llvm::BitstreamEntry::Record: Error("invalid record at top-level of AST file"); return Failure; + + case llvm::BitstreamEntry::SubBlock: + break; } - unsigned BlockID = Stream.ReadSubBlockID(); - // We only know the control subblock ID. - switch (BlockID) { + switch (Entry.ID) { case llvm::bitc::BLOCKINFO_BLOCK_ID: if (Stream.ReadBlockInfoBlock()) { Error("malformed BlockInfoBlock in AST file"); @@ -2846,11 +3142,13 @@ ASTReader::ReadASTCore(StringRef FileName, } break; case CONTROL_BLOCK_ID: + HaveReadControlBlock = true; switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) { case Success: break; case Failure: return Failure; + case Missing: return Missing; case OutOfDate: return OutOfDate; case VersionMismatch: return VersionMismatch; case ConfigurationMismatch: return ConfigurationMismatch; @@ -2858,8 +3156,14 @@ ASTReader::ReadASTCore(StringRef FileName, } break; case AST_BLOCK_ID: + if (!HaveReadControlBlock) { + if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) + Diag(diag::warn_pch_version_too_old); + return VersionMismatch; + } + // Record that we've loaded this module. - Loaded.push_back(M); + Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc)); return Success; default: @@ -3004,7 +3308,9 @@ void ASTReader::InitializeContext() { // 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); + makeModuleVisible(Imported, Module::AllVisible, + /*ImportLoc=*/SourceLocation(), + /*Complain=*/false); } ImportedModules.clear(); } @@ -3013,11 +3319,41 @@ void ASTReader::finalizeForWriting() { for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(), HiddenEnd = HiddenNamesMap.end(); Hidden != HiddenEnd; ++Hidden) { - makeNamesVisible(Hidden->second); + makeNamesVisible(Hidden->second, Hidden->first); } HiddenNamesMap.clear(); } +/// SkipCursorToControlBlock - Given a cursor at the start of an AST file, scan +/// ahead and drop the cursor into the start of the CONTROL_BLOCK, returning +/// false on success and true on failure. +static bool SkipCursorToControlBlock(BitstreamCursor &Cursor) { + while (1) { + llvm::BitstreamEntry Entry = Cursor.advance(); + switch (Entry.Kind) { + case llvm::BitstreamEntry::Error: + case llvm::BitstreamEntry::EndBlock: + return true; + + case llvm::BitstreamEntry::Record: + // Ignore top-level records. + Cursor.skipRecord(Entry.ID); + break; + + case llvm::BitstreamEntry::SubBlock: + if (Entry.ID == CONTROL_BLOCK_ID) { + if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID)) + return true; + // Found it! + return false; + } + + if (Cursor.SkipBlock()) + return true; + } + } +} + /// \brief Retrieve the name of the original source file name /// directly from the AST file, without actually loading the AST /// file. @@ -3035,7 +3371,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, // Initialize the stream llvm::BitstreamReader StreamFile; - llvm::BitstreamCursor Stream; + BitstreamCursor Stream; StreamFile.init((const unsigned char *)Buffer->getBufferStart(), (const unsigned char *)Buffer->getBufferEnd()); Stream.init(StreamFile); @@ -3048,54 +3384,30 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName; return std::string(); } + + // Scan for the CONTROL_BLOCK_ID block. + if (SkipCursorToControlBlock(Stream)) { + Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; + return std::string(); + } + // Scan for ORIGINAL_FILE inside the control block. RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - unsigned BlockID = Stream.ReadSubBlockID(); - - // We only know the AST subblock ID. - switch (BlockID) { - case CONTROL_BLOCK_ID: - if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) { - Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; - return std::string(); - } - break; - - default: - if (Stream.SkipBlock()) { - Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; - return std::string(); - } - break; - } - continue; - } - - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName; - return std::string(); - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; + while (1) { + llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + if (Entry.Kind == llvm::BitstreamEntry::EndBlock) + return std::string(); + + if (Entry.Kind != llvm::BitstreamEntry::Record) { + Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; + return std::string(); } - + Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == ORIGINAL_FILE) - return std::string(BlobStart, BlobLen); + StringRef Blob; + if (Stream.readRecord(Entry.ID, Record, &Blob) == ORIGINAL_FILE) + return Blob.str(); } - - return std::string(); } namespace { @@ -3147,7 +3459,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, // Initialize the stream llvm::BitstreamReader StreamFile; - llvm::BitstreamCursor Stream; + BitstreamCursor Stream; StreamFile.init((const unsigned char *)Buffer->getBufferStart(), (const unsigned char *)Buffer->getBufferEnd()); Stream.init(StreamFile); @@ -3160,105 +3472,71 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, return true; } + // Scan for the CONTROL_BLOCK_ID block. + if (SkipCursorToControlBlock(Stream)) + return true; + + // Scan for ORIGINAL_FILE inside the control block. RecordData Record; - bool InControlBlock = false; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - unsigned BlockID = Stream.ReadSubBlockID(); - - // We only know the control subblock ID. - switch (BlockID) { - case CONTROL_BLOCK_ID: - if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) { - return true; - } else { - InControlBlock = true; - } - break; - - default: - if (Stream.SkipBlock()) - return true; - break; - } - continue; - } - - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { + while (1) { + llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + if (Entry.Kind == llvm::BitstreamEntry::EndBlock) + return false; + + if (Entry.Kind != llvm::BitstreamEntry::Record) + return true; + + Record.clear(); + StringRef Blob; + unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); + switch ((ControlRecordTypes)RecCode) { + case METADATA: { + if (Record[0] != VERSION_MAJOR) return true; - } - InControlBlock = false; - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; + if (Listener.ReadFullVersionInformation(Blob)) + return true; + + break; } + case LANGUAGE_OPTIONS: + if (ParseLanguageOptions(Record, false, Listener)) + return true; + break; - Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen); - if (InControlBlock) { - switch ((ControlRecordTypes)RecCode) { - case METADATA: { - if (Record[0] != VERSION_MAJOR) { - return true; - } - - const std::string &CurBranch = getClangFullRepositoryVersion(); - StringRef ASTBranch(BlobStart, BlobLen); - if (StringRef(CurBranch) != ASTBranch) - return true; - - break; - } - case LANGUAGE_OPTIONS: - if (ParseLanguageOptions(Record, false, Listener)) - return true; - break; - - case TARGET_OPTIONS: - if (ParseTargetOptions(Record, false, Listener)) - return true; - break; + case TARGET_OPTIONS: + if (ParseTargetOptions(Record, false, Listener)) + return true; + break; - case DIAGNOSTIC_OPTIONS: - if (ParseDiagnosticOptions(Record, false, Listener)) - return true; - break; + case DIAGNOSTIC_OPTIONS: + if (ParseDiagnosticOptions(Record, false, Listener)) + return true; + break; - case FILE_SYSTEM_OPTIONS: - if (ParseFileSystemOptions(Record, false, Listener)) - return true; - break; + case FILE_SYSTEM_OPTIONS: + if (ParseFileSystemOptions(Record, false, Listener)) + return true; + break; - case HEADER_SEARCH_OPTIONS: - if (ParseHeaderSearchOptions(Record, false, Listener)) - return true; - break; + case HEADER_SEARCH_OPTIONS: + if (ParseHeaderSearchOptions(Record, false, Listener)) + return true; + break; - case PREPROCESSOR_OPTIONS: { - std::string IgnoredSuggestedPredefines; - if (ParsePreprocessorOptions(Record, false, Listener, - IgnoredSuggestedPredefines)) - return true; - break; - } + case PREPROCESSOR_OPTIONS: { + std::string IgnoredSuggestedPredefines; + if (ParsePreprocessorOptions(Record, false, Listener, + IgnoredSuggestedPredefines)) + return true; + break; + } - default: - // No other validation to perform. - break; - } + default: + // No other validation to perform. + break; } } - - return false; } @@ -3283,35 +3561,24 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { 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 true; - } - return false; - } + llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks(); - 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 true; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - F.Stream.ReadAbbrevRecord(); - continue; + switch (Entry.Kind) { + case llvm::BitstreamEntry::SubBlock: // Handled for us already. + case llvm::BitstreamEntry::Error: + Error("malformed block record in AST file"); + return true; + case llvm::BitstreamEntry::EndBlock: + return false; + case llvm::BitstreamEntry::Record: + // The interesting case. + break; } - + // Read a record. - const char *BlobStart; - unsigned BlobLen; + StringRef Blob; Record.clear(); - switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + switch (F.Stream.readRecord(Entry.ID, Record, &Blob)) { default: // Default behavior: ignore. break; @@ -3321,12 +3588,12 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { return true; } - if (Record.size() < 7) { + if (Record.size() < 8) { Error("malformed module definition"); return true; } - StringRef Name(BlobStart, BlobLen); + StringRef Name = Blob; SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]); SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]); bool IsFramework = Record[2]; @@ -3335,7 +3602,8 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { bool InferSubmodules = Record[5]; bool InferExplicitSubmodules = Record[6]; bool InferExportWildcard = Record[7]; - + bool ConfigMacrosExhaustive = Record[8]; + Module *ParentModule = 0; if (Parent) ParentModule = getSubmodule(Parent); @@ -3351,17 +3619,39 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { Error("too many submodules"); return true; } + + if (!ParentModule) { + if (const FileEntry *CurFile = CurrentModule->getASTFile()) { + if (CurFile != F.File) { + if (!Diags.isDiagnosticInFlight()) { + Diag(diag::err_module_file_conflict) + << CurrentModule->getTopLevelModuleName() + << CurFile->getName() + << F.File->getName(); + } + return true; + } + } + + CurrentModule->setASTFile(F.File); + } - CurrentModule->setASTFile(F.File); CurrentModule->IsFromModuleFile = true; CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; CurrentModule->InferSubmodules = InferSubmodules; CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; CurrentModule->InferExportWildcard = InferExportWildcard; + CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive; if (DeserializationListener) DeserializationListener->ModuleRead(GlobalID, CurrentModule); SubmodulesLoaded[GlobalIndex] = CurrentModule; + + // Clear out data that will be replaced by what is the module file. + CurrentModule->LinkLibraries.clear(); + CurrentModule->ConfigMacros.clear(); + CurrentModule->UnresolvedConflicts.clear(); + CurrentModule->Conflicts.clear(); break; } @@ -3374,8 +3664,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - StringRef FileName(BlobStart, BlobLen); - if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) { + if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) { if (!CurrentModule->getUmbrellaHeader()) ModMap.setUmbrellaHeader(CurrentModule, Umbrella); else if (CurrentModule->getUmbrellaHeader() != Umbrella) { @@ -3395,14 +3684,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { 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, false); - } + // We lazily associate headers with their modules via the HeaderInfoTable. + // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead + // of complete filenames or remove it entirely. break; } @@ -3415,14 +3699,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { 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, true); - } + // We lazily associate headers with their modules via the HeaderInfoTable. + // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead + // of complete filenames or remove it entirely. break; } @@ -3435,10 +3714,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - // FIXME: Be more lazy about this! - StringRef FileName(BlobStart, BlobLen); - if (const FileEntry *File = PP.getFileManager().getFile(FileName)) - CurrentModule->TopHeaders.insert(File); + CurrentModule->addTopHeaderFilename(Blob); break; } @@ -3451,9 +3727,8 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - StringRef DirName(BlobStart, BlobLen); if (const DirectoryEntry *Umbrella - = PP.getFileManager().getDirectory(DirName)) { + = PP.getFileManager().getDirectory(Blob)) { if (!CurrentModule->getUmbrellaDir()) ModMap.setUmbrellaDir(CurrentModule, Umbrella); else if (CurrentModule->getUmbrellaDir() != Umbrella) { @@ -3500,13 +3775,13 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { break; for (unsigned Idx = 0; Idx != Record.size(); ++Idx) { - UnresolvedModuleImportExport Unresolved; + UnresolvedModuleRef Unresolved; Unresolved.File = &F; Unresolved.Mod = CurrentModule; Unresolved.ID = Record[Idx]; - Unresolved.IsImport = true; + Unresolved.Kind = UnresolvedModuleRef::Import; Unresolved.IsWildcard = false; - UnresolvedModuleImportExports.push_back(Unresolved); + UnresolvedModuleRefs.push_back(Unresolved); } break; } @@ -3521,13 +3796,13 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { break; for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { - UnresolvedModuleImportExport Unresolved; + UnresolvedModuleRef Unresolved; Unresolved.File = &F; Unresolved.Mod = CurrentModule; Unresolved.ID = Record[Idx]; - Unresolved.IsImport = false; + Unresolved.Kind = UnresolvedModuleRef::Export; Unresolved.IsWildcard = Record[Idx + 1]; - UnresolvedModuleImportExports.push_back(Unresolved); + UnresolvedModuleRefs.push_back(Unresolved); } // Once we've loaded the set of exports, there's no reason to keep @@ -3544,11 +3819,55 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - CurrentModule->addRequirement(StringRef(BlobStart, BlobLen), - Context.getLangOpts(), + CurrentModule->addRequirement(Blob, Context.getLangOpts(), Context.getTargetInfo()); break; } + + case SUBMODULE_LINK_LIBRARY: + if (First) { + Error("missing submodule metadata record at beginning of block"); + return true; + } + + if (!CurrentModule) + break; + + CurrentModule->LinkLibraries.push_back( + Module::LinkLibrary(Blob, Record[0])); + break; + + case SUBMODULE_CONFIG_MACRO: + if (First) { + Error("missing submodule metadata record at beginning of block"); + return true; + } + + if (!CurrentModule) + break; + + CurrentModule->ConfigMacros.push_back(Blob.str()); + break; + + case SUBMODULE_CONFLICT: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return true; + } + + if (!CurrentModule) + break; + + UnresolvedModuleRef Unresolved; + Unresolved.File = &F; + Unresolved.Mod = CurrentModule; + Unresolved.ID = Record[0]; + Unresolved.Kind = UnresolvedModuleRef::Conflict; + Unresolved.IsWildcard = false; + Unresolved.String = Blob; + UnresolvedModuleRefs.push_back(Unresolved); + break; + } } } } @@ -3570,6 +3889,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++])); #include "clang/Basic/LangOptions.def" +#define SANITIZER(NAME, ID) LangOpts.Sanitize.ID = Record[Idx++]; +#include "clang/Basic/Sanitizers.def" ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++]; VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx); @@ -3578,6 +3899,15 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, unsigned Length = Record[Idx++]; LangOpts.CurrentModule.assign(Record.begin() + Idx, Record.begin() + Idx + Length); + + Idx += Length; + + // Comment options. + for (unsigned N = Record[Idx++]; N; --N) { + LangOpts.CommentOpts.BlockCommandNames.push_back( + ReadString(Record, Idx)); + } + return Listener.ReadLanguageOptions(LangOpts, Complain); } @@ -3637,14 +3967,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, std::string Path = ReadString(Record, Idx); frontend::IncludeDirGroup Group = static_cast<frontend::IncludeDirGroup>(Record[Idx++]); - bool IsUserSupplied = Record[Idx++]; bool IsFramework = Record[Idx++]; bool IgnoreSysRoot = Record[Idx++]; - bool IsInternal = Record[Idx++]; - bool ImplicitExternC = Record[Idx++]; HSOpts.UserEntries.push_back( - HeaderSearchOptions::Entry(Path, Group, IsUserSupplied, IsFramework, - IgnoreSysRoot, IsInternal, ImplicitExternC)); + HeaderSearchOptions::Entry(Path, Group, IsFramework, IgnoreSysRoot)); } // System header prefixes. @@ -3735,41 +4061,28 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { unsigned LocalIndex = PPInfo.second; const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; - SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); - M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset); - - unsigned Code = M.PreprocessorDetailCursor.ReadCode(); - switch (Code) { - case llvm::bitc::END_BLOCK: - return 0; - - case llvm::bitc::ENTER_SUBBLOCK: - Error("unexpected subblock record in preprocessor detail block"); - return 0; - - case llvm::bitc::DEFINE_ABBREV: - Error("unexpected abbrevation record in preprocessor detail block"); - return 0; - - default: - break; - } - if (!PP.getPreprocessingRecord()) { Error("no preprocessing record"); return 0; } + SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); + M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset); + + llvm::BitstreamEntry Entry = + M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); + if (Entry.Kind != llvm::BitstreamEntry::Record) + return 0; + // Read the record. SourceRange Range(ReadSourceLocation(M, PPOffs.Begin), ReadSourceLocation(M, PPOffs.End)); PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); - const char *BlobStart = 0; - unsigned BlobLen = 0; + StringRef Blob; RecordData Record; PreprocessorDetailRecordTypes RecType = - (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.ReadRecord( - Code, Record, BlobStart, BlobLen); + (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.readRecord( + Entry.ID, Record, &Blob); switch (RecType) { case PPD_MACRO_EXPANSION: { bool isBuiltin = Record[0]; @@ -3806,8 +4119,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { } case PPD_INCLUSION_DIRECTIVE: { - const char *FullFileNameStart = BlobStart + Record[0]; - StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]); + const char *FullFileNameStart = Blob.data() + Record[0]; + StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]); const FileEntry *File = 0; if (!FullFileName.empty()) File = PP.getFileManager().getFile(FullFileName); @@ -3817,7 +4130,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { = static_cast<InclusionDirective::InclusionKind>(Record[2]); InclusionDirective *ID = new (PPRec) InclusionDirective(PPRec, Kind, - StringRef(BlobStart, Record[0]), + StringRef(Blob.data(), Record[0]), Record[1], Record[3], File, Range); @@ -3885,7 +4198,7 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { GlobalSLocOffsetMapType::const_iterator SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - - BLoc.getOffset()); + BLoc.getOffset() - 1); assert(SLocMapI != GlobalSLocOffsetMap.end() && "Corrupted global sloc offset map"); @@ -3933,7 +4246,7 @@ ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const { GlobalSLocOffsetMapType::const_iterator SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - - ELoc.getOffset()); + ELoc.getOffset() - 1); assert(SLocMapI != GlobalSLocOffsetMap.end() && "Corrupted global sloc offset map"); @@ -3969,7 +4282,7 @@ std::pair<unsigned, unsigned> /// \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, +Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, FileID FID) { if (FID.isInvalid()) return false; @@ -3992,32 +4305,25 @@ llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, namespace { /// \brief Visitor used to search for information about a header file. class HeaderFileInfoVisitor { - ASTReader &Reader; const FileEntry *FE; - llvm::Optional<HeaderFileInfo> HFI; + Optional<HeaderFileInfo> HFI; public: - HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE) - : Reader(Reader), FE(FE) { } + explicit HeaderFileInfoVisitor(const FileEntry *FE) + : FE(FE) { } static bool visit(ModuleFile &M, void *UserData) { HeaderFileInfoVisitor *This = static_cast<HeaderFileInfoVisitor *>(UserData); - HeaderFileInfoTrait Trait(This->Reader, M, - &This->Reader.getPreprocessor().getHeaderSearchInfo(), - M.HeaderFileFrameworkStrings, - This->FE->getName()); - HeaderFileInfoLookupTable *Table = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable); if (!Table) return false; // Look in the on-disk hash table for an entry for this file name. - HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE->getName(), - &Trait); + HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE); if (Pos == Table->end()) return false; @@ -4025,14 +4331,14 @@ namespace { return true; } - llvm::Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; } + Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; } }; } HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { - HeaderFileInfoVisitor Visitor(*this, FE); + HeaderFileInfoVisitor Visitor(FE); ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor); - if (llvm::Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) { + if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) { if (Listener) Listener->ReadHeaderFileInfo(*HFI, FE->getUID()); return *HFI; @@ -4043,7 +4349,7 @@ HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { // FIXME: Make it work properly with modules. - llvm::SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates; + SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates; for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) { ModuleFile &F = *(*I); unsigned Idx = 0; @@ -4103,7 +4409,7 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { /// IDs. QualType ASTReader::readTypeRecord(unsigned Index) { RecordLocation Loc = TypeCursorForIndex(Index); - llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; + BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; // Keep track of where we are in the stream, then jump back there // after reading this type. @@ -4118,7 +4424,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { DeclsCursor.JumpToBit(Loc.Offset); RecordData Record; unsigned Code = DeclsCursor.ReadCode(); - switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) { + switch ((TypeCode)DeclsCursor.readRecord(Code, Record)) { case TYPE_EXT_QUAL: { if (Record.size() != 2) { Error("Incorrect encoding of extended qualifier type"); @@ -4287,8 +4593,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { } else if (EST == EST_Unevaluated) { EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); } - return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams, - EPI); + return Context.getFunctionType(ResultType, ParamTypes, EPI); } case TYPE_UNRESOLVED_USING: { @@ -4392,7 +4697,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { QualType Pattern = readType(*Loc.F, Record, Idx); if (Pattern.isNull()) return QualType(); - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; if (Record[1]) NumExpansions = Record[1] - 1; return Context.getPackExpansionType(Pattern, NumExpansions); @@ -4834,6 +5139,14 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_OBJC_ID: T = Context.ObjCBuiltinIdTy; break; case PREDEF_TYPE_OBJC_CLASS: T = Context.ObjCBuiltinClassTy; break; case PREDEF_TYPE_OBJC_SEL: T = Context.ObjCBuiltinSelTy; break; + case PREDEF_TYPE_IMAGE1D_ID: T = Context.OCLImage1dTy; break; + case PREDEF_TYPE_IMAGE1D_ARR_ID: T = Context.OCLImage1dArrayTy; break; + case PREDEF_TYPE_IMAGE1D_BUFF_ID: T = Context.OCLImage1dBufferTy; break; + case PREDEF_TYPE_IMAGE2D_ID: T = Context.OCLImage2dTy; break; + case PREDEF_TYPE_IMAGE2D_ARR_ID: T = Context.OCLImage2dArrayTy; break; + case PREDEF_TYPE_IMAGE3D_ID: T = Context.OCLImage3dTy; break; + case PREDEF_TYPE_SAMPLER_ID: T = Context.OCLSamplerTy; break; + case PREDEF_TYPE_EVENT_ID: T = Context.OCLEventTy; break; case PREDEF_TYPE_AUTO_DEDUCT: T = Context.getAutoDeductType(); break; case PREDEF_TYPE_AUTO_RREF_DEDUCT: @@ -4957,13 +5270,13 @@ uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Recor CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { RecordLocation Loc = getLocalBitOffset(Offset); - llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor; + BitstreamCursor &Cursor = Loc.F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(Loc.Offset); ReadingKindTracker ReadingKind(Read_Decl, *this); RecordData Record; unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.ReadRecord(Code, Record); + unsigned RecCode = Cursor.readRecord(Code, Record); if (RecCode != DECL_CXX_BASE_SPECIFIERS) { Error("Malformed AST file: missing C++ base specifiers"); return 0; @@ -4997,7 +5310,7 @@ bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, return &M == I->second; } -ModuleFile *ASTReader::getOwningModuleFile(Decl *D) { +ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { if (!D->isFromASTFile()) return 0; GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); @@ -5269,7 +5582,7 @@ namespace { /// declaration context. class DeclContextNameLookupVisitor { ASTReader &Reader; - llvm::SmallVectorImpl<const DeclContext *> &Contexts; + SmallVectorImpl<const DeclContext *> &Contexts; DeclarationName Name; SmallVectorImpl<NamedDecl *> &Decls; @@ -5333,14 +5646,34 @@ namespace { }; } -DeclContext::lookup_result +/// \brief Retrieve the "definitive" module file for the definition of the +/// given declaration context, if there is one. +/// +/// The "definitive" module file is the only place where we need to look to +/// find information about the declarations within the given declaration +/// context. For example, C++ and Objective-C classes, C structs/unions, and +/// Objective-C protocols, categories, and extensions are all defined in a +/// single place in the source code, so they have definitive module files +/// associated with them. C++ namespaces, on the other hand, can have +/// definitions in multiple different module files. +/// +/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's +/// NDEBUG checking. +static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC, + ASTReader &Reader) { + if (const DeclContext *DefDC = getDefinitiveDeclContext(DC)) + return Reader.getOwningModuleFile(cast<Decl>(DefDC)); + + return 0; +} + +bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { assert(DC->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); if (!Name) - return DeclContext::lookup_result(DeclContext::lookup_iterator(0), - DeclContext::lookup_iterator(0)); + return false; SmallVector<NamedDecl *, 64> Decls; @@ -5361,10 +5694,19 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, } DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); - ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); + + // If we can definitively determine which module file to look into, + // only look there. Otherwise, look in all module files. + ModuleFile *Definitive; + if (Contexts.size() == 1 && + (Definitive = getDefinitiveModuleFileFor(DC, *this))) { + DeclContextNameLookupVisitor::visit(*Definitive, &Visitor); + } else { + ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); + } ++NumVisibleDeclContextsRead; SetExternalVisibleDeclsForName(DC, Name, Decls); - return const_cast<DeclContext*>(DC)->lookup(Name); + return !Decls.empty(); } namespace { @@ -5372,15 +5714,17 @@ namespace { /// declaration context. class DeclContextAllNamesVisitor { ASTReader &Reader; - llvm::SmallVectorImpl<const DeclContext *> &Contexts; + SmallVectorImpl<const DeclContext *> &Contexts; llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls; + bool VisitAll; public: DeclContextAllNamesVisitor(ASTReader &Reader, SmallVectorImpl<const DeclContext *> &Contexts, llvm::DenseMap<DeclarationName, - SmallVector<NamedDecl *, 8> > &Decls) - : Reader(Reader), Contexts(Contexts), Decls(Decls) { } + SmallVector<NamedDecl *, 8> > &Decls, + bool VisitAll) + : Reader(Reader), Contexts(Contexts), Decls(Decls), VisitAll(VisitAll) { } static bool visit(ModuleFile &M, void *UserData) { DeclContextAllNamesVisitor *This @@ -5406,8 +5750,9 @@ namespace { Info->second.NameLookupTableData; bool FoundAnything = false; for (ASTDeclContextNameLookupTable::data_iterator - I = LookupTable->data_begin(), E = LookupTable->data_end(); - I != E; ++I) { + I = LookupTable->data_begin(), E = LookupTable->data_end(); + I != E; + ++I) { ASTDeclContextNameLookupTrait::data_type Data = *I; for (; Data.first != Data.second; ++Data.first) { NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, @@ -5421,7 +5766,7 @@ namespace { } } - return FoundAnything; + return FoundAnything && !This->VisitAll; } }; } @@ -5429,7 +5774,7 @@ namespace { void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { if (!DC->hasExternalVisibleStorage()) return; - llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls; + llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > Decls; // Compute the declaration contexts we need to look into. Multiple such // declaration contexts occur when two declaration contexts from disjoint @@ -5447,12 +5792,13 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { } } - DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls); + DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls, + /*VisitAll=*/DC->isFileContext()); ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor); ++NumVisibleDeclContextsRead; for (llvm::DenseMap<DeclarationName, - llvm::SmallVector<NamedDecl*, 8> >::iterator + SmallVector<NamedDecl *, 8> >::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { SetExternalVisibleDeclsForName(DC, I->first, I->second); } @@ -5576,8 +5922,31 @@ void ASTReader::PrintStats() { NumMethodPoolEntriesRead, TotalNumMethodPoolEntries, ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries * 100)); - std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses); } + if (NumMethodPoolLookups) { + std::fprintf(stderr, " %u/%u method pool lookups succeeded (%f%%)\n", + NumMethodPoolHits, NumMethodPoolLookups, + ((float)NumMethodPoolHits/NumMethodPoolLookups * 100.0)); + } + if (NumMethodPoolTableLookups) { + std::fprintf(stderr, " %u/%u method pool table lookups succeeded (%f%%)\n", + NumMethodPoolTableHits, NumMethodPoolTableLookups, + ((float)NumMethodPoolTableHits/NumMethodPoolTableLookups + * 100.0)); + } + + if (NumIdentifierLookupHits) { + std::fprintf(stderr, + " %u / %u identifier table lookups succeeded (%f%%)\n", + NumIdentifierLookupHits, NumIdentifierLookups, + (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups); + } + + if (GlobalIndex) { + std::fprintf(stderr, "\n"); + GlobalIndex->printStats(); + } + std::fprintf(stderr, "\n"); dump(); std::fprintf(stderr, "\n"); @@ -5646,8 +6015,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) { - SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I], - PreloadedDecls[I]->getDeclName()); + NamedDecl *ND = cast<NamedDecl>(PreloadedDecls[I]->getMostRecentDecl()); + SemaObj->pushExternalDeclIntoScope(ND, PreloadedDecls[I]->getDeclName()); } PreloadedDecls.clear(); @@ -5678,10 +6047,21 @@ void ASTReader::InitializeSema(Sema &S) { IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { // Note that we are loading an identifier. Deserializing AnIdentifier(this); - - IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart), - /*PriorGeneration=*/0); - ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); + StringRef Name(NameStart, NameEnd - NameStart); + + // If there is a global index, look there first to determine which modules + // provably do not have any results for this identifier. + GlobalModuleIndex::HitSet Hits; + GlobalModuleIndex::HitSet *HitsPtr = 0; + if (!loadGlobalIndex()) { + if (GlobalIndex->lookupIdentifier(Name, Hits)) { + HitsPtr = &Hits; + } + } + IdentifierLookupVisitor Visitor(Name, /*PriorGeneration=*/0, + NumIdentifierLookups, + NumIdentifierLookupHits); + ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor, HitsPtr); IdentifierInfo *II = Visitor.getIdentifierInfo(); markIdentifierUpToDate(II); return II; @@ -5737,9 +6117,9 @@ StringRef ASTIdentifierIterator::Next() { // We have any identifiers remaining in the current AST file; return // the next one. - std::pair<const char*, unsigned> Key = *Current; + StringRef Result = *Current; ++Current; - return StringRef(Key.first, Key.second); + return Result; } IdentifierIterator *ASTReader::getIdentifiers() const { @@ -5751,8 +6131,8 @@ namespace clang { namespace serialization { ASTReader &Reader; Selector Sel; unsigned PriorGeneration; - llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods; - llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods; + SmallVector<ObjCMethodDecl *, 4> InstanceMethods; + SmallVector<ObjCMethodDecl *, 4> FactoryMethods; public: ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, @@ -5770,12 +6150,14 @@ namespace clang { namespace serialization { if (M.Generation <= This->PriorGeneration) return true; + ++This->Reader.NumMethodPoolTableLookups; ASTSelectorLookupTable *PoolTable = (ASTSelectorLookupTable*)M.SelectorLookupTable; ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel); if (Pos == PoolTable->end()) return false; - + + ++This->Reader.NumMethodPoolTableHits; ++This->Reader.NumSelectorsRead; // FIXME: Not quite happy with the statistics here. We probably should // disable this tracking when called via LoadSelector. @@ -5818,15 +6200,16 @@ void ASTReader::ReadMethodPool(Selector Sel) { Generation = CurrentGeneration; // Search for methods defined with this selector. + ++NumMethodPoolLookups; ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration); ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor); if (Visitor.getInstanceMethods().empty() && - Visitor.getFactoryMethods().empty()) { - ++NumMethodPoolMisses; + Visitor.getFactoryMethods().empty()) return; - } - + + ++NumMethodPoolHits; + if (!getSema()) return; @@ -5849,6 +6232,16 @@ void ASTReader::ReadKnownNamespaces( } } +void ASTReader::ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) { + for (unsigned Idx = 0, N = UndefinedButUsed.size(); Idx != N;) { + NamedDecl *D = cast<NamedDecl>(GetDecl(UndefinedButUsed[Idx++])); + SourceLocation Loc = + SourceLocation::getFromRawEncoding(UndefinedButUsed[Idx++]); + Undefined.insert(std::make_pair(D, Loc)); + } +} + void ASTReader::ReadTentativeDefinitions( SmallVectorImpl<VarDecl *> &TentativeDefs) { for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { @@ -5902,14 +6295,14 @@ void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) { } void -ASTReader::ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl *> &Decls) { - for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) { - NamedDecl *D - = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I])); +ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) { + for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) { + NamedDecl *D + = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternCDecls[I])); if (D) Decls.push_back(D); } - LocallyScopedExternalDecls.clear(); + LocallyScopedExternCDecls.clear(); } void ASTReader::ReadReferencedSelectors( @@ -6000,28 +6393,32 @@ void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) { /// \param DeclIDs the set of declaration IDs with the name @p II that are /// visible at global scope. /// -/// \param Nonrecursive should be true to indicate that the caller knows that -/// this call is non-recursive, and therefore the globally-visible declarations -/// will not be placed onto the pending queue. +/// \param Decls if non-null, this vector will be populated with the set of +/// deserialized declarations. These declarations will not be pushed into +/// scope. void ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, const SmallVectorImpl<uint32_t> &DeclIDs, - bool Nonrecursive) { - if (NumCurrentElementsDeserializing && !Nonrecursive) { - PendingIdentifierInfos.push_back(PendingIdentifierInfo()); - PendingIdentifierInfo &PII = PendingIdentifierInfos.back(); - PII.II = II; - PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end()); + SmallVectorImpl<Decl *> *Decls) { + if (NumCurrentElementsDeserializing && !Decls) { + PendingIdentifierInfos[II].append(DeclIDs.begin(), DeclIDs.end()); return; } for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); if (SemaObj) { + // If we're simply supposed to record the declarations, do so now. + if (Decls) { + Decls->push_back(D); + continue; + } + // Introduce this declaration into the translation-unit scope // and add it to the declaration chain for this identifier, so // that (unqualified) name lookup will find it. - SemaObj->pushExternalDeclIntoScope(D, II); + NamedDecl *ND = cast<NamedDecl>(D->getMostRecentDecl()); + SemaObj->pushExternalDeclIntoScope(ND, II); } else { // Queue this declaration so that it will be added to the // translation unit scope and identifier's declaration chain @@ -6081,7 +6478,7 @@ IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { return LocalID + I->second; } -MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) { +MacroInfo *ASTReader::getMacro(MacroID ID) { if (ID == 0) return 0; @@ -6097,7 +6494,11 @@ MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) { assert(I != GlobalMacroMap.end() && "Corrupted global macro map"); ModuleFile *M = I->second; unsigned Index = ID - M->BaseMacroID; - ReadMacroRecord(*M, M->MacroOffsets[Index], Hint); + MacrosLoaded[ID] = ReadMacroRecord(*M, M->MacroOffsets[Index]); + + if (DeserializationListener) + DeserializationListener->MacroRead(ID + NUM_PREDEF_MACRO_IDS, + MacrosLoaded[ID]); } return MacrosLoaded[ID]; @@ -6140,7 +6541,11 @@ Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; } - + +Module *ASTReader::getModule(unsigned ID) { + return getSubmodule(ID); +} + Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { return DecodeSelector(getGlobalSelectorID(M, LocalID)); } @@ -6370,7 +6775,7 @@ ASTReader::ReadTemplateArgument(ModuleFile &F, return TemplateArgument(ReadTemplateName(F, Record, Idx)); case TemplateArgument::TemplateExpansion: { TemplateName Name = ReadTemplateName(F, Record, Idx); - llvm::Optional<unsigned> NumTemplateExpansions; + Optional<unsigned> NumTemplateExpansions; if (unsigned NumExpansions = Record[Idx++]) NumTemplateExpansions = NumExpansions - 1; return TemplateArgument(Name, NumTemplateExpansions); @@ -6420,13 +6825,14 @@ ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, } /// \brief Read a UnresolvedSet structure. -void ASTReader::ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, +void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; + Set.reserve(Context, NumDecls); while (NumDecls--) { NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addDecl(D, AS); + Set.addDecl(Context, D, AS); } } @@ -6656,8 +7062,10 @@ llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) { } /// \brief Read a floating-point value -llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) { - return llvm::APFloat(ReadAPInt(Record, Idx)); +llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, + const llvm::fltSemantics &Sem, + unsigned &Idx) { + return llvm::APFloat(Sem, ReadAPInt(Record, Idx)); } // \brief Read a string @@ -6721,39 +7129,35 @@ void ASTReader::ClearSwitchCaseIDs() { void ASTReader::ReadComments() { std::vector<RawComment *> Comments; - for (SmallVectorImpl<std::pair<llvm::BitstreamCursor, + for (SmallVectorImpl<std::pair<BitstreamCursor, serialization::ModuleFile *> >::iterator I = CommentsCursors.begin(), E = CommentsCursors.end(); I != E; ++I) { - llvm::BitstreamCursor &Cursor = I->first; + BitstreamCursor &Cursor = I->first; serialization::ModuleFile &F = *I->second; SavedStreamPosition SavedPosition(Cursor); RecordData Record; while (true) { - unsigned Code = Cursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) + llvm::BitstreamEntry Entry = + Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); + + switch (Entry.Kind) { + case llvm::BitstreamEntry::SubBlock: // Handled for us already. + case llvm::BitstreamEntry::Error: + Error("malformed block record in AST file"); + return; + case llvm::BitstreamEntry::EndBlock: + goto NextCursor; + case llvm::BitstreamEntry::Record: + // The interesting case. break; - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - Cursor.ReadSubBlockID(); - if (Cursor.SkipBlock()) { - Error("malformed block record in AST file"); - return; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Cursor.ReadAbbrevRecord(); - continue; } // Read a record. Record.clear(); - switch ((CommentRecordTypes) Cursor.ReadRecord(Code, Record)) { + switch ((CommentRecordTypes)Cursor.readRecord(Entry.ID, Record)) { case COMMENTS_RAW_COMMENT: { unsigned Idx = 0; SourceRange SR = ReadSourceRange(F, Record, Idx); @@ -6768,19 +7172,24 @@ void ASTReader::ReadComments() { } } } + NextCursor:; } Context.Comments.addCommentsToFront(Comments); } void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() || - !PendingMacroIDs.empty()) { + !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. + llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > TopLevelDecls; while (!PendingIdentifierInfos.empty()) { - SetGloballyVisibleDecls(PendingIdentifierInfos.front().II, - PendingIdentifierInfos.front().DeclIDs, true); - PendingIdentifierInfos.pop_front(); + // FIXME: std::move + IdentifierInfo *II = PendingIdentifierInfos.back().first; + SmallVector<uint32_t, 4> DeclIDs = PendingIdentifierInfos.back().second; + PendingIdentifierInfos.pop_back(); + + SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]); } // Load pending declaration chains. @@ -6790,17 +7199,48 @@ void ASTReader::finishPendingActions() { } PendingDeclChains.clear(); + // Make the most recent of the top-level declarations visible. + for (llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> >::iterator + TLD = TopLevelDecls.begin(), TLDEnd = TopLevelDecls.end(); + TLD != TLDEnd; ++TLD) { + IdentifierInfo *II = TLD->first; + for (unsigned I = 0, N = TLD->second.size(); I != N; ++I) { + NamedDecl *ND = cast<NamedDecl>(TLD->second[I]->getMostRecentDecl()); + SemaObj->pushExternalDeclIntoScope(ND, II); + } + } + // Load any pending macro definitions. for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) { - // FIXME: std::move here - SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second; - MacroInfo *Hint = 0; + IdentifierInfo *II = PendingMacroIDs.begin()[I].first; + SmallVector<PendingMacroInfo, 2> GlobalIDs; + GlobalIDs.swap(PendingMacroIDs.begin()[I].second); + // Initialize the macro history from chained-PCHs ahead of module imports. for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; ++IDIdx) { - Hint = getMacro(GlobalIDs[IDIdx], Hint); + const PendingMacroInfo &Info = GlobalIDs[IDIdx]; + if (Info.M->Kind != MK_Module) + resolvePendingMacro(II, Info); + } + // Handle module imports. + for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs; + ++IDIdx) { + const PendingMacroInfo &Info = GlobalIDs[IDIdx]; + if (Info.M->Kind == MK_Module) + resolvePendingMacro(II, Info); } } PendingMacroIDs.clear(); + + // Wire up the DeclContexts for Decls that we delayed setting until + // recursive loading is completed. + while (!PendingDeclContextInfos.empty()) { + PendingDeclContextInfo Info = PendingDeclContextInfos.front(); + PendingDeclContextInfos.pop_front(); + DeclContext *SemaDC = cast<DeclContext>(GetDecl(Info.SemaDC)); + DeclContext *LexicalDC = cast<DeclContext>(GetDecl(Info.LexicalDC)); + Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext()); + } } // If we deserialized any C++ or Objective-C class definitions, any @@ -6908,18 +7348,22 @@ void ASTReader::FinishedDeserializing() { ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, bool DisableValidation, - bool AllowASTWithCompilerErrors) + bool AllowASTWithCompilerErrors, bool UseGlobalIndex) : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), Consumer(0), ModuleMgr(PP.getFileManager()), isysroot(isysroot), DisableValidation(DisableValidation), - AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), + AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), + UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false), CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts), NumSLocEntriesRead(0), TotalNumSLocEntries(0), - NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), - TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), - NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), + NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), + TotalNumMacros(0), NumIdentifierLookups(0), NumIdentifierLookupHits(0), + NumSelectorsRead(0), NumMethodPoolEntriesRead(0), + NumMethodPoolLookups(0), NumMethodPoolHits(0), + NumMethodPoolTableLookups(0), NumMethodPoolTableHits(0), + TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), |