diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-12 01:31:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-12 01:31:05 +0000 |
commit | b64c19365deab788753d29c9bc881253c3f16f37 (patch) | |
tree | 904471327e615a25388412991745290bf92b668f /lib/Frontend/PCHReader.cpp | |
parent | 06ab044127f0ff9a2b3696b6787d23c877505292 (diff) |
Make precompiled headers work with -E. When we're only preprocessing
(with -E), we turn the PCH include into an implicit include of the
file from which the PCH file was generated.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71534 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 759865c7eb..ab7ad04e9d 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1218,6 +1218,10 @@ PCHReader::ReadPCHBlock() { } ObjCCategoryImpls.swap(Record); break; + + case pch::ORIGINAL_FILE_NAME: + OriginalFileName.assign(BlobStart, BlobLen); + break; } } Error("premature end of bitstream in PCH file"); @@ -1364,6 +1368,87 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { return Success; } +/// \brief Retrieve the name of the original source file name +/// directly from the PCH file, without actually loading the PCH +/// file. +std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { + // Open the PCH file. + std::string ErrStr; + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr)); + if (!Buffer) { + fprintf(stderr, "error: %s\n", ErrStr.c_str()); + return std::string(); + } + + // Initialize the stream + llvm::BitstreamReader StreamFile; + llvm::BitstreamCursor Stream; + StreamFile.init((const unsigned char *)Buffer->getBufferStart(), + (const unsigned char *)Buffer->getBufferEnd()); + Stream.init(StreamFile); + + // Sniff for the signature. + if (Stream.Read(8) != 'C' || + Stream.Read(8) != 'P' || + Stream.Read(8) != 'C' || + Stream.Read(8) != 'H') { + fprintf(stderr, + "error: '%s' does not appear to be a precompiled header file\n", + PCHFileName.c_str()); + return std::string(); + } + + RecordData Record; + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + + if (Code == llvm::bitc::ENTER_SUBBLOCK) { + unsigned BlockID = Stream.ReadSubBlockID(); + + // We only know the PCH subblock ID. + switch (BlockID) { + case pch::PCH_BLOCK_ID: + if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { + fprintf(stderr, "error: malformed block record in PCH file\n"); + return std::string(); + } + break; + + default: + if (Stream.SkipBlock()) { + fprintf(stderr, "error: malformed block record in PCH file\n"); + return std::string(); + } + break; + } + continue; + } + + if (Code == llvm::bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) { + fprintf(stderr, "error: error at end of module block in PCH file\n"); + return std::string(); + } + continue; + } + + if (Code == llvm::bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + Record.clear(); + const char *BlobStart = 0; + unsigned BlobLen = 0; + if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) + == pch::ORIGINAL_FILE_NAME) + return std::string(BlobStart, BlobLen); + } + + return std::string(); +} + /// \brief Parse the record that corresponds to a LangOptions data /// structure. /// |