diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-10 03:52:48 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-10 03:52:48 +0000 |
commit | 14f79002e58556798e86168c63e48d533287eda5 (patch) | |
tree | abf9da0e0bb6aea4cdb6ce2a744d1e018d045dbc /lib/Frontend/PCHReader.cpp | |
parent | 52e5602056e4cade24cbcca57767e94e1d430b03 (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.cpp | 85 |
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()) |