Teach the PCH reader to load the dependency when encountering a chain metadata record. WIP
llvm-svn: 108578
diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp
index 7b95b89..6111037 100644
--- a/clang/lib/Frontend/PCHReader.cpp
+++ b/clang/lib/Frontend/PCHReader.cpp
@@ -1447,6 +1447,39 @@
default: // Default behavior: ignore.
break;
+ case pch::METADATA: {
+ if (Record[0] != pch::VERSION_MAJOR) {
+ Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return IgnorePCH;
+ }
+
+ RelocatablePCH = Record[4];
+ if (Listener) {
+ std::string TargetTriple(BlobStart, BlobLen);
+ if (Listener->ReadTargetTriple(TargetTriple))
+ return IgnorePCH;
+ }
+ break;
+ }
+
+ case pch::CHAINED_METADATA: {
+ if (Record[0] != pch::VERSION_MAJOR) {
+ Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return IgnorePCH;
+ }
+
+ // Load the chained file.
+ switch(ReadPCHCore(llvm::StringRef(BlobStart, BlobLen))) {
+ case Failure: return Failure;
+ // If we have to ignore the dependency, we'll have to ignore this too.
+ case IgnorePCH: return IgnorePCH;
+ case Success: break;
+ }
+ break;
+ }
+
case pch::TYPE_OFFSET:
if (!TypesLoaded.empty()) {
Error("duplicate TYPE_OFFSET record in PCH file");
@@ -1470,22 +1503,6 @@
return IgnorePCH;
break;
- case pch::METADATA: {
- if (Record[0] != pch::VERSION_MAJOR) {
- Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
- : diag::warn_pch_version_too_new);
- return IgnorePCH;
- }
-
- RelocatablePCH = Record[4];
- if (Listener) {
- std::string TargetTriple(BlobStart, BlobLen);
- if (Listener->ReadTargetTriple(TargetTriple))
- return IgnorePCH;
- }
- break;
- }
-
case pch::IDENTIFIER_TABLE:
IdentifierTableData = BlobStart;
if (Record[0]) {
@@ -1658,13 +1675,90 @@
}
PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
- switch(OpenPCH(FileName)) {
+ switch(ReadPCHCore(FileName)) {
case Failure: return Failure;
case IgnorePCH: return IgnorePCH;
case Success: break;
}
+
+ // Here comes stuff that we only do once the entire chain is loaded.
+
+ // Check the predefines buffers.
+ if (CheckPredefinesBuffers())
+ return IgnorePCH;
+
+ if (PP) {
+ // Initialization of keywords and pragmas occurs before the
+ // PCH file is read, so there may be some identifiers that were
+ // loaded into the IdentifierTable before we intercepted the
+ // creation of identifiers. Iterate through the list of known
+ // identifiers and determine whether we have to establish
+ // preprocessor definitions or top-level identifier declaration
+ // chains for those identifiers.
+ //
+ // We copy the IdentifierInfo pointers to a small vector first,
+ // since de-serializing declarations or macro definitions can add
+ // new entries into the identifier table, invalidating the
+ // iterators.
+ llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+ for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+ IdEnd = PP->getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Identifiers.push_back(Id->second);
+ PCHIdentifierLookupTable *IdTable
+ = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+ for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+ IdentifierInfo *II = Identifiers[I];
+ // Look in the on-disk hash table for an entry for
+ PCHIdentifierLookupTrait Info(*this, II);
+ std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
+ PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of populating the
+ // IdentifierInfo node with the various declarations it needs.
+ (void)*Pos;
+ }
+ }
+
+ if (Context)
+ InitializeContext(*Context);
+
+ return Success;
+}
+
+PCHReader::PCHReadResult PCHReader::ReadPCHCore(llvm::StringRef FileName) {
+ Chain.push_back(new PerFileData());
PerFileData &F = *Chain.back();
+
+ // Set the PCH file name.
+ F.FileName = FileName;
+
+ // Open the PCH file.
+ //
+ // FIXME: This shouldn't be here, we should just take a raw_ostream.
+ std::string ErrStr;
+ F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
+ if (!F.Buffer) {
+ Error(ErrStr.c_str());
+ return IgnorePCH;
+ }
+
+ // Initialize the stream
+ F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(),
+ (const unsigned char *)F.Buffer->getBufferEnd());
llvm::BitstreamCursor &Stream = F.Stream;
+ Stream.init(F.StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ Diag(diag::err_not_a_pch_file) << FileName;
+ return Failure;
+ }
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
@@ -1717,91 +1811,6 @@
}
}
- // Check the predefines buffers.
- if (CheckPredefinesBuffers())
- return IgnorePCH;
-
- if (PP) {
- // Initialization of keywords and pragmas occurs before the
- // PCH file is read, so there may be some identifiers that were
- // loaded into the IdentifierTable before we intercepted the
- // creation of identifiers. Iterate through the list of known
- // identifiers and determine whether we have to establish
- // preprocessor definitions or top-level identifier declaration
- // chains for those identifiers.
- //
- // We copy the IdentifierInfo pointers to a small vector first,
- // since de-serializing declarations or macro definitions can add
- // new entries into the identifier table, invalidating the
- // iterators.
- llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
- for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
- IdEnd = PP->getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Identifiers.push_back(Id->second);
- PCHIdentifierLookupTable *IdTable
- = (PCHIdentifierLookupTable *)IdentifierLookupTable;
- for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
- IdentifierInfo *II = Identifiers[I];
- // Look in the on-disk hash table for an entry for
- PCHIdentifierLookupTrait Info(*this, II);
- std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
- PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
- if (Pos == IdTable->end())
- continue;
-
- // Dereferencing the iterator has the effect of populating the
- // IdentifierInfo node with the various declarations it needs.
- (void)*Pos;
- }
- }
-
- if (Context)
- InitializeContext(*Context);
-
- return Success;
-}
-
-PCHReader::PCHReadResult PCHReader::OpenPCH(llvm::StringRef FileName) {
- Chain.push_back(new PerFileData());
- PerFileData &F = *Chain.back();
-
- // Set the PCH file name.
- F.FileName = FileName;
-
- // Open the PCH file.
- //
- // FIXME: This shouldn't be here, we should just take a raw_ostream.
- std::string ErrStr;
- F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
- if (!F.Buffer) {
- Error(ErrStr.c_str());
- return IgnorePCH;
- }
-
- // Initialize the stream
- F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(),
- (const unsigned char *)F.Buffer->getBufferEnd());
- llvm::BitstreamCursor &Stream = F.Stream;
- Stream.init(F.StreamFile);
-
- // Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
- Diag(diag::err_not_a_pch_file) << FileName;
- return Failure;
- }
- return Success;
-}
-
-PCHReader::PCHReadResult PCHReader::ReadChainedPCH(llvm::StringRef FileName) {
- switch(OpenPCH(FileName)) {
- case Failure: return Failure;
- case IgnorePCH: return IgnorePCH;
- case Success: break;
- }
return Success;
}