summaryrefslogtreecommitdiffstats
path: root/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Serialization/ASTReader.cpp
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-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.cpp2238
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),
OpenPOWER on IntegriCloud