[cfe-commits] r71534 - in /cfe/trunk: include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/preprocess.c test/PCH/preprocess.h tools/clang-cc/clang-cc.cpp
Douglas Gregor
dgregor at apple.com
Mon May 11 18:31:06 PDT 2009
Author: dgregor
Date: Mon May 11 20:31:05 2009
New Revision: 71534
URL: http://llvm.org/viewvc/llvm-project?rev=71534&view=rev
Log:
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.
Added:
cfe/trunk/test/PCH/preprocess.c (with props)
cfe/trunk/test/PCH/preprocess.h (with props)
Modified:
cfe/trunk/include/clang/Frontend/PCHBitCodes.h
cfe/trunk/include/clang/Frontend/PCHReader.h
cfe/trunk/include/clang/Frontend/PCHWriter.h
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/tools/clang-cc/clang-cc.cpp
Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=71534&r1=71533&r2=71534&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Mon May 11 20:31:05 2009
@@ -214,7 +214,11 @@
/// \brief Record code for the set of Objective-C category
/// implementations.
- OBJC_CATEGORY_IMPLEMENTATIONS = 19
+ OBJC_CATEGORY_IMPLEMENTATIONS = 19,
+
+ /// \brief Record code for the original file that was used to
+ /// generate the precompiled header.
+ ORIGINAL_FILE_NAME = 20
};
/// \brief Record types used within a source manager block.
Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=71534&r1=71533&r2=71534&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Mon May 11 20:31:05 2009
@@ -216,6 +216,10 @@
/// the PCH file.
llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
+ /// \brief The original file name that was used to build the PCH
+ /// file.
+ std::string OriginalFileName;
+
/// \brief Mapping from switch-case IDs in the PCH file to
/// switch-case statements.
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
@@ -327,8 +331,18 @@
explicit PCHReader(Preprocessor &PP, ASTContext *Context);
~PCHReader();
+ /// \brief Load the precompiled header designated by the given file
+ /// name.
PCHReadResult ReadPCH(const std::string &FileName);
+ /// \brief Retrieve the name of the original source file name
+ const std::string &getOriginalSourceFile() { return OriginalFileName; }
+
+ /// \brief Retrieve the name of the original source file name
+ /// directly from the PCH file, without actually loading the PCH
+ /// file.
+ static std::string getOriginalSourceFile(const std::string &PCHFileName);
+
/// \brief Returns the suggested contents of the predefines buffer,
/// which contains a (typically-empty) subset of the predefines
/// build prior to including the precompiled header.
Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=71534&r1=71533&r2=71534&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Mon May 11 20:31:05 2009
@@ -160,7 +160,7 @@
unsigned NumVisibleDeclContexts;
void WriteBlockInfoBlock();
- void WriteMetadata(const TargetInfo &Target);
+ void WriteMetadata(ASTContext &Context);
void WriteLanguageOptions(const LangOptions &LangOpts);
void WriteStatCache(MemorizeStatCalls &StatCalls);
void WriteSourceManagerBlock(SourceManager &SourceMgr,
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=71534&r1=71533&r2=71534&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Mon May 11 20:31:05 2009
@@ -1218,6 +1218,10 @@
}
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 @@
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.
///
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=71534&r1=71533&r2=71534&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Mon May 11 20:31:05 2009
@@ -33,6 +33,7 @@
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Path.h"
#include <cstdio>
using namespace clang;
@@ -442,16 +443,44 @@
/// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
-void PCHWriter::WriteMetadata(const TargetInfo &Target) {
+void PCHWriter::WriteMetadata(ASTContext &Context) {
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::METADATA));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple
- unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+
+ // Original file name
+ SourceManager &SM = Context.getSourceManager();
+ if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+ BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
+ FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME));
+ FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+ unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
+
+ llvm::sys::Path MainFilePath(MainFile->getName());
+ std::string MainFileName;
+
+ if (!MainFilePath.isAbsolute()) {
+ llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
+ P.appendComponent(MainFilePath.toString());
+ MainFileName = P.toString();
+ } else {
+ MainFileName = MainFilePath.toString();
+ }
+
+ RecordData Record;
+ Record.push_back(pch::ORIGINAL_FILE_NAME);
+ Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileName.c_str(),
+ MainFileName.size());
+ }
+
+ // Metadata
+ const TargetInfo &Target = Context.Target;
+ BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
+ MetaAbbrev->Add(BitCodeAbbrevOp(pch::METADATA));
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple
+ unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
RecordData Record;
Record.push_back(pch::METADATA);
@@ -460,7 +489,7 @@
Record.push_back(CLANG_VERSION_MAJOR);
Record.push_back(CLANG_VERSION_MINOR);
const char *Triple = Target.getTargetTriple();
- Stream.EmitRecordWithBlob(AbbrevCode, Record, Triple, strlen(Triple));
+ Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple));
}
/// \brief Write the LangOptions structure.
@@ -1672,7 +1701,7 @@
// Write the remaining PCH contents.
RecordData Record;
Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
- WriteMetadata(Context.Target);
+ WriteMetadata(Context);
WriteLanguageOptions(Context.getLangOptions());
if (StatCalls)
WriteStatCache(*StatCalls);
Added: cfe/trunk/test/PCH/preprocess.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/preprocess.c?rev=71534&view=auto
==============================================================================
--- cfe/trunk/test/PCH/preprocess.c (added)
+++ cfe/trunk/test/PCH/preprocess.c Mon May 11 20:31:05 2009
@@ -0,0 +1,5 @@
+// RUN: clang-cc -emit-pch -o %t %S/preprocess.h &&
+// RUN: clang-cc -include-pch %t -E -o - %s | grep -c "a_typedef" | count 1
+#include "preprocess.h"
+
+int a_value;
Propchange: cfe/trunk/test/PCH/preprocess.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/PCH/preprocess.c
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/PCH/preprocess.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: cfe/trunk/test/PCH/preprocess.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/preprocess.h?rev=71534&view=auto
==============================================================================
--- cfe/trunk/test/PCH/preprocess.h (added)
+++ cfe/trunk/test/PCH/preprocess.h Mon May 11 20:31:05 2009
@@ -0,0 +1,7 @@
+// Helper header for preprocess.c PCH test
+#ifndef PREPROCESS_H
+#define PREPROCESS_H
+
+typedef int a_typedef;
+
+#endif // PREPROCESS_H
Propchange: cfe/trunk/test/PCH/preprocess.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/PCH/preprocess.h
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/PCH/preprocess.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=71534&r1=71533&r2=71534&view=diff
==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Mon May 11 20:31:05 2009
@@ -1267,7 +1267,8 @@
for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i)
InitOpts.addMacroInclude(ImplicitMacroIncludes[i]);
- if (!ImplicitIncludePTH.empty() || !ImplicitIncludes.empty()) {
+ if (!ImplicitIncludePTH.empty() || !ImplicitIncludes.empty() ||
+ (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)) {
// We want to add these paths to the predefines buffer in order, make a
// temporary vector to sort by their occurrence.
llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths;
@@ -1275,6 +1276,9 @@
if (!ImplicitIncludePTH.empty())
OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(),
&ImplicitIncludePTH));
+ if (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)
+ OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(),
+ &ImplicitIncludePCH));
for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i)
OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i),
&ImplicitIncludes[i]));
@@ -1288,9 +1292,18 @@
Ptr >= &ImplicitIncludes[0] &&
Ptr <= &ImplicitIncludes[ImplicitIncludes.size()-1]) {
InitOpts.addInclude(*Ptr, false);
- } else {
- assert(Ptr == &ImplicitIncludePTH);
+ } else if (Ptr == &ImplicitIncludePTH) {
InitOpts.addInclude(*Ptr, true);
+ } else {
+ // We end up here when we're producing preprocessed output and
+ // we loaded a PCH file. In this case, just include the header
+ // file that was used to build the precompiled header.
+ assert(Ptr == &ImplicitIncludePCH);
+ std::string OriginalFile = PCHReader::getOriginalSourceFile(*Ptr);
+ if (!OriginalFile.empty()) {
+ InitOpts.addInclude(OriginalFile, false);
+ ImplicitIncludePCH.clear();
+ }
}
}
}
More information about the cfe-commits
mailing list