aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/PCHReader.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-04-10 03:52:48 +0000
committerDouglas Gregor <dgregor@apple.com>2009-04-10 03:52:48 +0000
commit14f79002e58556798e86168c63e48d533287eda5 (patch)
treeabf9da0e0bb6aea4cdb6ce2a744d1e018d045dbc /lib/Frontend/PCHReader.cpp
parent52e5602056e4cade24cbcca57767e94e1d430b03 (diff)
PCH serialization/deserialization of the source manager. With this
improvement, source locations read from the PCH file will properly resolve to the source files that were used to build the PCH file itself. Once we have the preprocessor state stored in the PCH file, source locations that refer to macro instantiations that occur in the PCH file should have the appropriate instantiation information. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68758 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/PCHReader.cpp')
-rw-r--r--lib/Frontend/PCHReader.cpp85
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index d366cddf17..01a79b44d9 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -15,6 +15,9 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -111,6 +114,84 @@ static bool Error(const char *Str) {
return true;
}
+/// \brief Read the source manager block
+bool PCHReader::ReadSourceManagerBlock() {
+ using namespace SrcMgr;
+ if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID))
+ return Error("Malformed source manager block record");
+
+ SourceManager &SourceMgr = Context.getSourceManager();
+ RecordData Record;
+ while (true) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of Source Manager block");
+ return false;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case pch::SM_SLOC_FILE_ENTRY: {
+ // FIXME: We would really like to delay the creation of this
+ // FileEntry until it is actually required, e.g., when producing
+ // a diagnostic with a source location in this file.
+ const FileEntry *File
+ = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
+ // FIXME: Error recovery if file cannot be found.
+ SourceMgr.createFileID(File,
+ SourceLocation::getFromRawEncoding(Record[1]),
+ (CharacteristicKind)Record[2]);
+ break;
+ }
+
+ case pch::SM_SLOC_BUFFER_ENTRY: {
+ const char *Name = BlobStart;
+ unsigned Code = Stream.ReadCode();
+ Record.clear();
+ unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+ assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
+ SourceMgr.createFileIDForMemBuffer(
+ llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1,
+ Name));
+ break;
+ }
+
+ case pch::SM_SLOC_INSTANTIATION_ENTRY: {
+ SourceLocation SpellingLoc
+ = SourceLocation::getFromRawEncoding(Record[1]);
+ SourceMgr.createInstantiationLoc(
+ SpellingLoc,
+ SourceLocation::getFromRawEncoding(Record[2]),
+ SourceLocation::getFromRawEncoding(Record[3]),
+ Lexer::MeasureTokenLength(SpellingLoc,
+ SourceMgr));
+ break;
+ }
+
+ }
+ }
+}
+
/// \brief Read the type-offsets block.
bool PCHReader::ReadTypeOffsets() {
if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID))
@@ -217,6 +298,10 @@ bool PCHReader::ReadPCHBlock() {
return Error("Malformed block record");
break;
+ case pch::SOURCE_MANAGER_BLOCK_ID:
+ if (ReadSourceManagerBlock())
+ return Error("Malformed source manager block");
+ break;
case pch::TYPE_OFFSETS_BLOCK_ID:
if (ReadTypeOffsets())