зеркало из https://github.com/microsoft/clang.git
Introduce the notion of "Relocatable" precompiled headers, which are built
with a particular system root directory and can be used with a different system root directory when the headers it depends on have been installed. Relocatable precompiled headers rewrite the file names of the headers used when generating the PCH file into the corresponding file names of the headers available when using the PCH file. Addresses <rdar://problem/7001604>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74885 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
169077dde4
Коммит
e650c8c3bc
|
@ -465,6 +465,50 @@ for headers that are directly included within a source file. For example:</p>
|
||||||
<tt>test.h</tt> since <tt>test.h</tt> was included directly in the source file
|
<tt>test.h</tt> since <tt>test.h</tt> was included directly in the source file
|
||||||
and not specified on the command line using <tt>-include</tt>.</p>
|
and not specified on the command line using <tt>-include</tt>.</p>
|
||||||
|
|
||||||
|
<h4>Relocatable PCH Files</h4>
|
||||||
|
<p>It is sometimes necessary to build a precompiled header from headers that
|
||||||
|
are not yet in their final, installed locations. For example, one might build a
|
||||||
|
precompiled header within the build tree that is then meant to be installed
|
||||||
|
alongside the headers. Clang permits the creation of "relocatable" precompiled
|
||||||
|
headers, which are built with a given path (into the build directory) and can
|
||||||
|
later be used from an installed location.</p>
|
||||||
|
|
||||||
|
<p>To build a relocatable precompiled header, place your headers into a
|
||||||
|
subdirectory whose structure mimics the installed location. For example, if you
|
||||||
|
want to build a precompiled header for the header <code>mylib.h</code> that
|
||||||
|
will be installed into <code>/usr/include</code>, create a subdirectory
|
||||||
|
<code>build/usr/include</code> and place the header <code>mylib.h</code> into
|
||||||
|
that subdirectory. If <code>mylib.h</code> depends on other headers, then
|
||||||
|
they can be stored within <code>build/usr/include</code> in a way that mimics
|
||||||
|
the installed location.</p>
|
||||||
|
|
||||||
|
<p>Building a relocatable precompiled header requires two additional arguments.
|
||||||
|
First, pass the <code>--relocatable-pch</code> flag to indicate that the
|
||||||
|
resulting PCH file should be relocatable. Second, pass
|
||||||
|
<code>-isysroot /path/to/build</code>, which makes all includes for your
|
||||||
|
library relative to the build directory. For example:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
# clang -x c-header --relocatable-pch -isysroot /path/to/build /path/to/build/mylib.h mylib.h.pch
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>When loading the relocatable PCH file, the various headers used in the PCH
|
||||||
|
file are found from the system header root. For example, <code>mylib.h</code>
|
||||||
|
can be found in <code>/usr/include/mylib.h</code>. If the headers are installed
|
||||||
|
in some other system root, the <code>-isysroot</code> option can be used provide
|
||||||
|
a different system root from which the headers will be based. For example,
|
||||||
|
<code>-isysroot /Developer/SDKs/MacOSX10.4u.sdk</code> will look for
|
||||||
|
<code>mylib.h</code> in
|
||||||
|
<code>/Developer/SDKs/MacOSX10.4u.sdk/usr/include/mylib.h</code>.</p>
|
||||||
|
|
||||||
|
<p>Relocatable precompiled headers are intended to be used in a limited number
|
||||||
|
of cases where the compilation environment is tightly controlled and the
|
||||||
|
precompiled header cannot be generated after headers have been installed.
|
||||||
|
Relocatable precompiled headers also have some performance impact, because
|
||||||
|
the difference in location between the header locations at PCH build time vs.
|
||||||
|
at the time of PCH use requires one of the PCH optimizations,
|
||||||
|
<code>stat()</code> caching, to be disabled. However, this change is only
|
||||||
|
likely to affect PCH files that reference a large number of headers.</p>
|
||||||
|
|
||||||
<!-- ======================================================================= -->
|
<!-- ======================================================================= -->
|
||||||
<h2 id="c">C Language Features</h2>
|
<h2 id="c">C Language Features</h2>
|
||||||
|
|
|
@ -24,6 +24,9 @@ def warn_fixit_no_changes : Note<
|
||||||
"FIX-IT detected errors it could not fix; no output will be generated">;
|
"FIX-IT detected errors it could not fix; no output will be generated">;
|
||||||
|
|
||||||
// PCH reader
|
// PCH reader
|
||||||
|
def err_relocatable_without_without_isysroot : Error<
|
||||||
|
"must specify system root with -isysroot when building a relocatable "
|
||||||
|
"PCH file">;
|
||||||
def warn_pch_target_triple : Error<
|
def warn_pch_target_triple : Error<
|
||||||
"PCH file was compiled for the target '%0' but the current translation "
|
"PCH file was compiled for the target '%0' but the current translation "
|
||||||
"unit is being compiled for target '%1'">;
|
"unit is being compiled for target '%1'">;
|
||||||
|
|
|
@ -223,6 +223,8 @@ OPTION("--print-prog-name", _print_prog_name, Separate, INVALID, print_prog_name
|
||||||
OPTION("--print-search-dirs", _print_search_dirs, Flag, INVALID, print_search_dirs, "", 0, 0, 0)
|
OPTION("--print-search-dirs", _print_search_dirs, Flag, INVALID, print_search_dirs, "", 0, 0, 0)
|
||||||
OPTION("--profile-blocks", _profile_blocks, Flag, INVALID, a, "", 0, 0, 0)
|
OPTION("--profile-blocks", _profile_blocks, Flag, INVALID, a, "", 0, 0, 0)
|
||||||
OPTION("--profile", _profile, Flag, INVALID, p, "", 0, 0, 0)
|
OPTION("--profile", _profile, Flag, INVALID, p, "", 0, 0, 0)
|
||||||
|
OPTION("--relocatable-pch", _relocatable_pch, Flag, INVALID, INVALID, "", 0,
|
||||||
|
"Build a relocatable precompiled header", 0)
|
||||||
OPTION("--resource=", _resource_EQ, Joined, INVALID, fcompile_resource_EQ, "", 0, 0, 0)
|
OPTION("--resource=", _resource_EQ, Joined, INVALID, fcompile_resource_EQ, "", 0, 0, 0)
|
||||||
OPTION("--resource", _resource, Separate, INVALID, fcompile_resource_EQ, "J", 0, 0, 0)
|
OPTION("--resource", _resource, Separate, INVALID, fcompile_resource_EQ, "J", 0, 0, 0)
|
||||||
OPTION("--save-temps", _save_temps, Flag, INVALID, save_temps, "", 0, 0, 0)
|
OPTION("--save-temps", _save_temps, Flag, INVALID, save_temps, "", 0, 0, 0)
|
||||||
|
|
|
@ -92,7 +92,8 @@ ASTConsumer* CreateHTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D,
|
||||||
// used later with the PCHReader (clang-cc option -include-pch)
|
// used later with the PCHReader (clang-cc option -include-pch)
|
||||||
// to speed up compile times.
|
// to speed up compile times.
|
||||||
ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
|
ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
|
||||||
llvm::raw_ostream *OS);
|
llvm::raw_ostream *OS,
|
||||||
|
const char *isysroot = 0);
|
||||||
|
|
||||||
// Block rewriter: rewrites code using the Apple blocks extension to pure
|
// Block rewriter: rewrites code using the Apple blocks extension to pure
|
||||||
// C code. Output is always sent to stdout.
|
// C code. Output is always sent to stdout.
|
||||||
|
|
|
@ -310,6 +310,13 @@ private:
|
||||||
/// file.
|
/// file.
|
||||||
std::string OriginalFileName;
|
std::string OriginalFileName;
|
||||||
|
|
||||||
|
/// \brief Whether this precompiled header is a relocatable PCH file.
|
||||||
|
bool RelocatablePCH;
|
||||||
|
|
||||||
|
/// \brief The system include root to be used when loading the
|
||||||
|
/// precompiled header.
|
||||||
|
const char *isysroot;
|
||||||
|
|
||||||
/// \brief Mapping from switch-case IDs in the PCH file to
|
/// \brief Mapping from switch-case IDs in the PCH file to
|
||||||
/// switch-case statements.
|
/// switch-case statements.
|
||||||
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
|
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
|
||||||
|
@ -428,10 +435,13 @@ private:
|
||||||
/// predefines buffer may contain additional definitions.
|
/// predefines buffer may contain additional definitions.
|
||||||
std::string SuggestedPredefines;
|
std::string SuggestedPredefines;
|
||||||
|
|
||||||
|
void MaybeAddSystemRootToFilename(std::string &Filename);
|
||||||
|
|
||||||
PCHReadResult ReadPCHBlock();
|
PCHReadResult ReadPCHBlock();
|
||||||
bool CheckPredefinesBuffer(const char *PCHPredef,
|
bool CheckPredefinesBuffer(const char *PCHPredef,
|
||||||
unsigned PCHPredefLen,
|
unsigned PCHPredefLen,
|
||||||
FileID PCHBufferID);
|
FileID PCHBufferID);
|
||||||
|
bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
|
||||||
PCHReadResult ReadSourceManagerBlock();
|
PCHReadResult ReadSourceManagerBlock();
|
||||||
PCHReadResult ReadSLocEntryRecord(unsigned ID);
|
PCHReadResult ReadSLocEntryRecord(unsigned ID);
|
||||||
|
|
||||||
|
@ -448,19 +458,42 @@ private:
|
||||||
|
|
||||||
PCHReader(const PCHReader&); // do not implement
|
PCHReader(const PCHReader&); // do not implement
|
||||||
PCHReader &operator=(const PCHReader &); // do not implement
|
PCHReader &operator=(const PCHReader &); // do not implement
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef llvm::SmallVector<uint64_t, 64> RecordData;
|
typedef llvm::SmallVector<uint64_t, 64> RecordData;
|
||||||
|
|
||||||
/// \brief Load the PCH file and validate its contents against the given
|
/// \brief Load the PCH file and validate its contents against the given
|
||||||
/// Preprocessor.
|
/// Preprocessor.
|
||||||
PCHReader(Preprocessor &PP, ASTContext *Context);
|
///
|
||||||
|
/// \param PP the preprocessor associated with the context in which this
|
||||||
|
/// precompiled header will be loaded.
|
||||||
|
///
|
||||||
|
/// \param Context the AST context that this precompiled header will be
|
||||||
|
/// loaded into.
|
||||||
|
///
|
||||||
|
/// \param isysroot If non-NULL, the system include path specified by the
|
||||||
|
/// user. This is only used with relocatable PCH files. If non-NULL,
|
||||||
|
/// a relocatable PCH file will use the default path "/".
|
||||||
|
PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0);
|
||||||
|
|
||||||
/// \brief Load the PCH file without using any pre-initialized Preprocessor.
|
/// \brief Load the PCH file without using any pre-initialized Preprocessor.
|
||||||
///
|
///
|
||||||
/// The necessary information to initialize a Preprocessor later can be
|
/// The necessary information to initialize a Preprocessor later can be
|
||||||
/// obtained by setting a PCHReaderListener.
|
/// obtained by setting a PCHReaderListener.
|
||||||
PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, Diagnostic &Diags);
|
///
|
||||||
|
/// \param SourceMgr the source manager into which the precompiled header
|
||||||
|
/// will be loaded.
|
||||||
|
///
|
||||||
|
/// \param FileMgr the file manager into which the precompiled header will
|
||||||
|
/// be loaded.
|
||||||
|
///
|
||||||
|
/// \param Diags the diagnostics system to use for reporting errors and
|
||||||
|
/// warnings relevant to loading the precompiled header.
|
||||||
|
///
|
||||||
|
/// \param isysroot If non-NULL, the system include path specified by the
|
||||||
|
/// user. This is only used with relocatable PCH files. If non-NULL,
|
||||||
|
/// a relocatable PCH file will use the default path "/".
|
||||||
|
PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
|
||||||
|
Diagnostic &Diags, const char *isysroot = 0);
|
||||||
~PCHReader();
|
~PCHReader();
|
||||||
|
|
||||||
/// \brief Load the precompiled header designated by the given file
|
/// \brief Load the precompiled header designated by the given file
|
||||||
|
|
|
@ -160,11 +160,12 @@ private:
|
||||||
unsigned NumVisibleDeclContexts;
|
unsigned NumVisibleDeclContexts;
|
||||||
|
|
||||||
void WriteBlockInfoBlock();
|
void WriteBlockInfoBlock();
|
||||||
void WriteMetadata(ASTContext &Context);
|
void WriteMetadata(ASTContext &Context, const char *isysroot);
|
||||||
void WriteLanguageOptions(const LangOptions &LangOpts);
|
void WriteLanguageOptions(const LangOptions &LangOpts);
|
||||||
void WriteStatCache(MemorizeStatCalls &StatCalls);
|
void WriteStatCache(MemorizeStatCalls &StatCalls, const char* isysroot);
|
||||||
void WriteSourceManagerBlock(SourceManager &SourceMgr,
|
void WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||||
const Preprocessor &PP);
|
const Preprocessor &PP,
|
||||||
|
const char* isysroot);
|
||||||
void WritePreprocessor(const Preprocessor &PP);
|
void WritePreprocessor(const Preprocessor &PP);
|
||||||
void WriteComments(ASTContext &Context);
|
void WriteComments(ASTContext &Context);
|
||||||
void WriteType(const Type *T);
|
void WriteType(const Type *T);
|
||||||
|
@ -186,7 +187,17 @@ public:
|
||||||
PCHWriter(llvm::BitstreamWriter &Stream);
|
PCHWriter(llvm::BitstreamWriter &Stream);
|
||||||
|
|
||||||
/// \brief Write a precompiled header for the given semantic analysis.
|
/// \brief Write a precompiled header for the given semantic analysis.
|
||||||
void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls);
|
///
|
||||||
|
/// \param SemaRef a reference to the semantic analysis object that processed
|
||||||
|
/// the AST to be written into the precompiled header.
|
||||||
|
///
|
||||||
|
/// \param StatCalls the object that cached all of the stat() calls made while
|
||||||
|
/// searching for source files and headers.
|
||||||
|
///
|
||||||
|
/// \param isysroot if non-NULL, write a relocatable PCH file whose headers
|
||||||
|
/// are relative to the given system root.
|
||||||
|
void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||||
|
const char* isysroot);
|
||||||
|
|
||||||
/// \brief Emit a source location.
|
/// \brief Emit a source location.
|
||||||
void AddSourceLocation(SourceLocation Loc, RecordData &Record);
|
void AddSourceLocation(SourceLocation Loc, RecordData &Record);
|
||||||
|
|
|
@ -474,6 +474,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
CmdArgs.push_back(A->getValue(Args));
|
CmdArgs.push_back(A->getValue(Args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Args.hasArg(options::OPT__relocatable_pch, true))
|
||||||
|
CmdArgs.push_back("--relocatable-pch");
|
||||||
|
|
||||||
// Forward -f options which we can pass directly.
|
// Forward -f options which we can pass directly.
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_fexceptions);
|
Args.AddLastArg(CmdArgs, options::OPT_fexceptions);
|
||||||
|
|
|
@ -32,19 +32,24 @@ using namespace llvm;
|
||||||
namespace {
|
namespace {
|
||||||
class VISIBILITY_HIDDEN PCHGenerator : public SemaConsumer {
|
class VISIBILITY_HIDDEN PCHGenerator : public SemaConsumer {
|
||||||
const Preprocessor &PP;
|
const Preprocessor &PP;
|
||||||
|
const char *isysroot;
|
||||||
llvm::raw_ostream *Out;
|
llvm::raw_ostream *Out;
|
||||||
Sema *SemaPtr;
|
Sema *SemaPtr;
|
||||||
MemorizeStatCalls *StatCalls; // owned by the FileManager
|
MemorizeStatCalls *StatCalls; // owned by the FileManager
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *Out);
|
explicit PCHGenerator(const Preprocessor &PP,
|
||||||
|
const char *isysroot,
|
||||||
|
llvm::raw_ostream *Out);
|
||||||
virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
|
virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
|
||||||
virtual void HandleTranslationUnit(ASTContext &Ctx);
|
virtual void HandleTranslationUnit(ASTContext &Ctx);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
PCHGenerator::PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS)
|
PCHGenerator::PCHGenerator(const Preprocessor &PP,
|
||||||
: PP(PP), Out(OS), SemaPtr(0), StatCalls(0) {
|
const char *isysroot,
|
||||||
|
llvm::raw_ostream *OS)
|
||||||
|
: PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0) {
|
||||||
|
|
||||||
// Install a stat() listener to keep track of all of the stat()
|
// Install a stat() listener to keep track of all of the stat()
|
||||||
// calls.
|
// calls.
|
||||||
|
@ -56,14 +61,14 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
|
||||||
if (PP.getDiagnostics().hasErrorOccurred())
|
if (PP.getDiagnostics().hasErrorOccurred())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Write the PCH contents into a buffer
|
// Write the PCH contents into a buffer
|
||||||
std::vector<unsigned char> Buffer;
|
std::vector<unsigned char> Buffer;
|
||||||
BitstreamWriter Stream(Buffer);
|
BitstreamWriter Stream(Buffer);
|
||||||
PCHWriter Writer(Stream);
|
PCHWriter Writer(Stream);
|
||||||
|
|
||||||
// Emit the PCH file
|
// Emit the PCH file
|
||||||
assert(SemaPtr && "No Sema?");
|
assert(SemaPtr && "No Sema?");
|
||||||
Writer.WritePCH(*SemaPtr, StatCalls);
|
Writer.WritePCH(*SemaPtr, StatCalls, isysroot);
|
||||||
|
|
||||||
// Write the generated bitstream to "Out".
|
// Write the generated bitstream to "Out".
|
||||||
Out->write((char *)&Buffer.front(), Buffer.size());
|
Out->write((char *)&Buffer.front(), Buffer.size());
|
||||||
|
@ -73,6 +78,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
|
ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
|
||||||
llvm::raw_ostream *OS) {
|
llvm::raw_ostream *OS,
|
||||||
return new PCHGenerator(PP, OS);
|
const char *isysroot) {
|
||||||
|
return new PCHGenerator(PP, isysroot, OS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,7 +336,8 @@ void PCHValidator::ReadCounter(unsigned Value) {
|
||||||
// PCH reader implementation
|
// PCH reader implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
|
PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
|
||||||
|
const char *isysroot)
|
||||||
: Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
|
: Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
|
||||||
FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
|
FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
|
||||||
SemaObj(0), PP(&PP), Context(Context), Consumer(0),
|
SemaObj(0), PP(&PP), Context(Context), Consumer(0),
|
||||||
|
@ -344,25 +345,31 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
|
||||||
IdentifierOffsets(0),
|
IdentifierOffsets(0),
|
||||||
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
|
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
|
||||||
TotalSelectorsInMethodPool(0), SelectorOffsets(0),
|
TotalSelectorsInMethodPool(0), SelectorOffsets(0),
|
||||||
TotalNumSelectors(0), Comments(0), NumComments(0),
|
TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
|
||||||
NumStatHits(0), NumStatMisses(0),
|
NumStatHits(0), NumStatMisses(0),
|
||||||
NumSLocEntriesRead(0), NumStatementsRead(0),
|
NumSLocEntriesRead(0), NumStatementsRead(0),
|
||||||
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
|
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
|
||||||
NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
|
NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
|
||||||
|
CurrentlyLoadingTypeOrDecl(0) {
|
||||||
|
RelocatablePCH = false;
|
||||||
|
}
|
||||||
|
|
||||||
PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
|
PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
|
||||||
Diagnostic &Diags)
|
Diagnostic &Diags, const char *isysroot)
|
||||||
: SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
|
: SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
|
||||||
SemaObj(0), PP(0), Context(0), Consumer(0),
|
SemaObj(0), PP(0), Context(0), Consumer(0),
|
||||||
IdentifierTableData(0), IdentifierLookupTable(0),
|
IdentifierTableData(0), IdentifierLookupTable(0),
|
||||||
IdentifierOffsets(0),
|
IdentifierOffsets(0),
|
||||||
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
|
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
|
||||||
TotalSelectorsInMethodPool(0), SelectorOffsets(0),
|
TotalSelectorsInMethodPool(0), SelectorOffsets(0),
|
||||||
TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
|
TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
|
||||||
|
NumStatHits(0), NumStatMisses(0),
|
||||||
NumSLocEntriesRead(0), NumStatementsRead(0),
|
NumSLocEntriesRead(0), NumStatementsRead(0),
|
||||||
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
|
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
|
||||||
NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
|
NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
|
||||||
CurrentlyLoadingTypeOrDecl(0) { }
|
CurrentlyLoadingTypeOrDecl(0) {
|
||||||
|
RelocatablePCH = false;
|
||||||
|
}
|
||||||
|
|
||||||
PCHReader::~PCHReader() {}
|
PCHReader::~PCHReader() {}
|
||||||
|
|
||||||
|
@ -652,8 +659,7 @@ bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
|
||||||
|
|
||||||
/// \brief Read the line table in the source manager block.
|
/// \brief Read the line table in the source manager block.
|
||||||
/// \returns true if ther was an error.
|
/// \returns true if ther was an error.
|
||||||
static bool ParseLineTable(SourceManager &SourceMgr,
|
bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
|
||||||
llvm::SmallVectorImpl<uint64_t> &Record) {
|
|
||||||
unsigned Idx = 0;
|
unsigned Idx = 0;
|
||||||
LineTableInfo &LineTable = SourceMgr.getLineTable();
|
LineTableInfo &LineTable = SourceMgr.getLineTable();
|
||||||
|
|
||||||
|
@ -664,6 +670,7 @@ static bool ParseLineTable(SourceManager &SourceMgr,
|
||||||
unsigned FilenameLen = Record[Idx++];
|
unsigned FilenameLen = Record[Idx++];
|
||||||
std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
|
std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
|
||||||
Idx += FilenameLen;
|
Idx += FilenameLen;
|
||||||
|
MaybeAddSystemRootToFilename(Filename);
|
||||||
FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
|
FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
|
||||||
Filename.size());
|
Filename.size());
|
||||||
}
|
}
|
||||||
|
@ -859,7 +866,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case pch::SM_LINE_TABLE:
|
case pch::SM_LINE_TABLE:
|
||||||
if (ParseLineTable(SourceMgr, Record))
|
if (ParseLineTable(Record))
|
||||||
return Failure;
|
return Failure;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -912,10 +919,12 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
|
||||||
return Failure;
|
return Failure;
|
||||||
|
|
||||||
case pch::SM_SLOC_FILE_ENTRY: {
|
case pch::SM_SLOC_FILE_ENTRY: {
|
||||||
const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen);
|
std::string Filename(BlobStart, BlobStart + BlobLen);
|
||||||
|
MaybeAddSystemRootToFilename(Filename);
|
||||||
|
const FileEntry *File = FileMgr.getFile(Filename);
|
||||||
if (File == 0) {
|
if (File == 0) {
|
||||||
std::string ErrorStr = "could not find file '";
|
std::string ErrorStr = "could not find file '";
|
||||||
ErrorStr.append(BlobStart, BlobLen);
|
ErrorStr += Filename;
|
||||||
ErrorStr += "' referenced by PCH file";
|
ErrorStr += "' referenced by PCH file";
|
||||||
Error(ErrorStr.c_str());
|
Error(ErrorStr.c_str());
|
||||||
return Failure;
|
return Failure;
|
||||||
|
@ -1096,6 +1105,32 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief If we are loading a relocatable PCH file, and the filename is
|
||||||
|
/// not an absolute path, add the system root to the beginning of the file
|
||||||
|
/// name.
|
||||||
|
void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
|
||||||
|
// If this is not a relocatable PCH file, there's nothing to do.
|
||||||
|
if (!RelocatablePCH)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<')
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string FIXME = Filename;
|
||||||
|
|
||||||
|
if (isysroot == 0) {
|
||||||
|
// If no system root was given, default to '/'
|
||||||
|
Filename.insert(Filename.begin(), '/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Length = strlen(isysroot);
|
||||||
|
if (isysroot[Length - 1] != '/')
|
||||||
|
Filename.insert(Filename.begin(), '/');
|
||||||
|
|
||||||
|
Filename.insert(Filename.begin(), isysroot, isysroot + Length);
|
||||||
|
}
|
||||||
|
|
||||||
PCHReader::PCHReadResult
|
PCHReader::PCHReadResult
|
||||||
PCHReader::ReadPCHBlock() {
|
PCHReader::ReadPCHBlock() {
|
||||||
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
|
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
|
||||||
|
@ -1208,6 +1243,7 @@ PCHReader::ReadPCHBlock() {
|
||||||
return IgnorePCH;
|
return IgnorePCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RelocatablePCH = Record[4];
|
||||||
if (Listener) {
|
if (Listener) {
|
||||||
std::string TargetTriple(BlobStart, BlobLen);
|
std::string TargetTriple(BlobStart, BlobLen);
|
||||||
if (Listener->ReadTargetTriple(TargetTriple))
|
if (Listener->ReadTargetTriple(TargetTriple))
|
||||||
|
@ -1338,6 +1374,7 @@ PCHReader::ReadPCHBlock() {
|
||||||
|
|
||||||
case pch::ORIGINAL_FILE_NAME:
|
case pch::ORIGINAL_FILE_NAME:
|
||||||
OriginalFileName.assign(BlobStart, BlobLen);
|
OriginalFileName.assign(BlobStart, BlobLen);
|
||||||
|
MaybeAddSystemRootToFilename(OriginalFileName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case pch::COMMENT_RANGES:
|
case pch::COMMENT_RANGES:
|
||||||
|
|
|
@ -476,11 +476,68 @@ void PCHWriter::WriteBlockInfoBlock() {
|
||||||
Stream.ExitBlock();
|
Stream.ExitBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Adjusts the given filename to only write out the portion of the
|
||||||
|
/// filename that is not part of the system root directory.
|
||||||
|
///
|
||||||
|
/// \param Filename the file name to adjust.
|
||||||
|
///
|
||||||
|
/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and
|
||||||
|
/// the returned filename will be adjusted by this system root.
|
||||||
|
///
|
||||||
|
/// \returns either the original filename (if it needs no adjustment) or the
|
||||||
|
/// adjusted filename (which points into the @p Filename parameter).
|
||||||
|
static const char *
|
||||||
|
adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) {
|
||||||
|
assert(Filename && "No file name to adjust?");
|
||||||
|
|
||||||
|
if (!isysroot)
|
||||||
|
return Filename;
|
||||||
|
|
||||||
|
// Verify that the filename and the system root have the same prefix.
|
||||||
|
unsigned Pos = 0;
|
||||||
|
for (; Filename[Pos] && isysroot[Pos]; ++Pos)
|
||||||
|
if (Filename[Pos] != isysroot[Pos])
|
||||||
|
return Filename; // Prefixes don't match.
|
||||||
|
|
||||||
|
// We hit the end of the filename before we hit the end of the system root.
|
||||||
|
if (!Filename[Pos])
|
||||||
|
return Filename;
|
||||||
|
|
||||||
|
// If the file name has a '/' at the current position, skip over the '/'.
|
||||||
|
// We distinguish sysroot-based includes from absolute includes by the
|
||||||
|
// absence of '/' at the beginning of sysroot-based includes.
|
||||||
|
if (Filename[Pos] == '/')
|
||||||
|
++Pos;
|
||||||
|
|
||||||
|
return Filename + Pos;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
|
/// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
|
||||||
void PCHWriter::WriteMetadata(ASTContext &Context) {
|
void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
// 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::Fixed, 1)); // Relocatable
|
||||||
|
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple
|
||||||
|
unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
|
||||||
|
|
||||||
|
RecordData Record;
|
||||||
|
Record.push_back(pch::METADATA);
|
||||||
|
Record.push_back(pch::VERSION_MAJOR);
|
||||||
|
Record.push_back(pch::VERSION_MINOR);
|
||||||
|
Record.push_back(CLANG_VERSION_MAJOR);
|
||||||
|
Record.push_back(CLANG_VERSION_MINOR);
|
||||||
|
Record.push_back(isysroot != 0);
|
||||||
|
const char *Triple = Target.getTargetTriple();
|
||||||
|
Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple));
|
||||||
|
|
||||||
// Original file name
|
// Original file name
|
||||||
SourceManager &SM = Context.getSourceManager();
|
SourceManager &SM = Context.getSourceManager();
|
||||||
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
|
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
|
||||||
|
@ -500,31 +557,14 @@ void PCHWriter::WriteMetadata(ASTContext &Context) {
|
||||||
MainFileName = MainFilePath.toString();
|
MainFileName = MainFilePath.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *MainFileNameStr = MainFileName.c_str();
|
||||||
|
MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
|
||||||
|
isysroot);
|
||||||
RecordData Record;
|
RecordData Record;
|
||||||
Record.push_back(pch::ORIGINAL_FILE_NAME);
|
Record.push_back(pch::ORIGINAL_FILE_NAME);
|
||||||
Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileName.c_str(),
|
Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr,
|
||||||
MainFileName.size());
|
strlen(MainFileNameStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
Record.push_back(pch::VERSION_MAJOR);
|
|
||||||
Record.push_back(pch::VERSION_MINOR);
|
|
||||||
Record.push_back(CLANG_VERSION_MAJOR);
|
|
||||||
Record.push_back(CLANG_VERSION_MINOR);
|
|
||||||
const char *Triple = Target.getTargetTriple();
|
|
||||||
Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Write the LangOptions structure.
|
/// \brief Write the LangOptions structure.
|
||||||
|
@ -649,15 +689,19 @@ public:
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
/// \brief Write the stat() system call cache to the PCH file.
|
/// \brief Write the stat() system call cache to the PCH file.
|
||||||
void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
|
void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls,
|
||||||
|
const char *isysroot) {
|
||||||
// Build the on-disk hash table containing information about every
|
// Build the on-disk hash table containing information about every
|
||||||
// stat() call.
|
// stat() call.
|
||||||
OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator;
|
OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator;
|
||||||
unsigned NumStatEntries = 0;
|
unsigned NumStatEntries = 0;
|
||||||
for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
|
for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
|
||||||
StatEnd = StatCalls.end();
|
StatEnd = StatCalls.end();
|
||||||
Stat != StatEnd; ++Stat, ++NumStatEntries)
|
Stat != StatEnd; ++Stat, ++NumStatEntries) {
|
||||||
Generator.insert(Stat->first(), Stat->second);
|
const char *Filename = Stat->first();
|
||||||
|
Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
|
||||||
|
Generator.insert(Filename, Stat->second);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the on-disk hash table in a buffer.
|
// Create the on-disk hash table in a buffer.
|
||||||
llvm::SmallVector<char, 4096> StatCacheData;
|
llvm::SmallVector<char, 4096> StatCacheData;
|
||||||
|
@ -753,7 +797,8 @@ static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
|
||||||
/// errors), we probably won't have to create file entries for any of
|
/// errors), we probably won't have to create file entries for any of
|
||||||
/// the files in the AST.
|
/// the files in the AST.
|
||||||
void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||||
const Preprocessor &PP) {
|
const Preprocessor &PP,
|
||||||
|
const char *isysroot) {
|
||||||
RecordData Record;
|
RecordData Record;
|
||||||
|
|
||||||
// Enter the source manager block.
|
// Enter the source manager block.
|
||||||
|
@ -774,6 +819,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||||
for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
|
for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
|
||||||
// Emit the file name
|
// Emit the file name
|
||||||
const char *Filename = LineTable.getFilename(I);
|
const char *Filename = LineTable.getFilename(I);
|
||||||
|
Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
|
||||||
unsigned FilenameLen = Filename? strlen(Filename) : 0;
|
unsigned FilenameLen = Filename? strlen(Filename) : 0;
|
||||||
Record.push_back(FilenameLen);
|
Record.push_back(FilenameLen);
|
||||||
if (FilenameLen)
|
if (FilenameLen)
|
||||||
|
@ -850,9 +896,21 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||||
if (Content->Entry) {
|
if (Content->Entry) {
|
||||||
// The source location entry is a file. The blob associated
|
// The source location entry is a file. The blob associated
|
||||||
// with this entry is the file name.
|
// with this entry is the file name.
|
||||||
Stream.EmitRecordWithBlob(SLocFileAbbrv, Record,
|
|
||||||
Content->Entry->getName(),
|
// Turn the file name into an absolute path, if it isn't already.
|
||||||
strlen(Content->Entry->getName()));
|
const char *Filename = Content->Entry->getName();
|
||||||
|
llvm::sys::Path FilePath(Filename, strlen(Filename));
|
||||||
|
std::string FilenameStr;
|
||||||
|
if (!FilePath.isAbsolute()) {
|
||||||
|
llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
|
||||||
|
P.appendComponent(FilePath.toString());
|
||||||
|
FilenameStr = P.toString();
|
||||||
|
Filename = FilenameStr.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
|
||||||
|
Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename,
|
||||||
|
strlen(Filename));
|
||||||
|
|
||||||
// FIXME: For now, preload all file source locations, so that
|
// FIXME: For now, preload all file source locations, so that
|
||||||
// we get the appropriate File entries in the reader. This is
|
// we get the appropriate File entries in the reader. This is
|
||||||
|
@ -1716,7 +1774,8 @@ PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
|
||||||
NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
|
NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
|
||||||
NumVisibleDeclContexts(0) { }
|
NumVisibleDeclContexts(0) { }
|
||||||
|
|
||||||
void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) {
|
void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||||
|
const char *isysroot) {
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
ASTContext &Context = SemaRef.Context;
|
ASTContext &Context = SemaRef.Context;
|
||||||
|
@ -1778,11 +1837,11 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) {
|
||||||
// Write the remaining PCH contents.
|
// Write the remaining PCH contents.
|
||||||
RecordData Record;
|
RecordData Record;
|
||||||
Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
|
Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
|
||||||
WriteMetadata(Context);
|
WriteMetadata(Context, isysroot);
|
||||||
WriteLanguageOptions(Context.getLangOptions());
|
WriteLanguageOptions(Context.getLangOptions());
|
||||||
if (StatCalls)
|
if (StatCalls && !isysroot)
|
||||||
WriteStatCache(*StatCalls);
|
WriteStatCache(*StatCalls, isysroot);
|
||||||
WriteSourceManagerBlock(Context.getSourceManager(), PP);
|
WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
|
||||||
WritePreprocessor(PP);
|
WritePreprocessor(PP);
|
||||||
WriteComments(Context);
|
WriteComments(Context);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef RELOC_H
|
||||||
|
#define RELOC_H
|
||||||
|
|
||||||
|
#include <reloc2.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Line number 13 below is important
|
||||||
|
int x = 2;
|
||||||
|
|
||||||
|
#endif // RELOC_H
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef RELOC2_H
|
||||||
|
#define RELOC2_H
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Line number below is important!
|
||||||
|
int y = 2;
|
||||||
|
#endif // RELOC2_H
|
|
@ -0,0 +1,14 @@
|
||||||
|
// RUN: clang-cc -emit-pch -o %t --relocatable-pch -isysroot `pwd`/libroot `pwd`/libroot/usr/include/reloc.h &&
|
||||||
|
// RUN: clang-cc -include-pch %t -isysroot `pwd`/libroot %s -verify
|
||||||
|
// FIXME (test harness can't do this?): not clang-cc -include-pch %t %s
|
||||||
|
|
||||||
|
#include <reloc.h>
|
||||||
|
|
||||||
|
int x = 2; // expected-error{{redefinition}}
|
||||||
|
int y = 5; // expected-error{{redefinition}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// expected-note{{previous definition}}
|
||||||
|
// expected-note{{previous definition}}
|
|
@ -1057,6 +1057,10 @@ static llvm::cl::opt<std::string>
|
||||||
ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
|
ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
|
||||||
llvm::cl::desc("Include file before parsing"));
|
llvm::cl::desc("Include file before parsing"));
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool>
|
||||||
|
RelocatablePCH("relocatable-pch",
|
||||||
|
llvm::cl::desc("Whether to build a relocatable precompiled "
|
||||||
|
"header"));
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Preprocessor include path information.
|
// Preprocessor include path information.
|
||||||
|
@ -1820,8 +1824,16 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
|
||||||
}
|
}
|
||||||
|
|
||||||
case GeneratePCH:
|
case GeneratePCH:
|
||||||
|
if (RelocatablePCH.getValue() && !isysroot.getNumOccurrences()) {
|
||||||
|
PP.Diag(SourceLocation(), diag::err_relocatable_without_without_isysroot);
|
||||||
|
RelocatablePCH.setValue(false);
|
||||||
|
}
|
||||||
|
|
||||||
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
|
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
|
||||||
Consumer.reset(CreatePCHGenerator(PP, OS.get()));
|
if (RelocatablePCH.getValue())
|
||||||
|
Consumer.reset(CreatePCHGenerator(PP, OS.get(), isysroot.c_str()));
|
||||||
|
else
|
||||||
|
Consumer.reset(CreatePCHGenerator(PP, OS.get()));
|
||||||
CompleteTranslationUnit = false;
|
CompleteTranslationUnit = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1978,7 +1990,13 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
|
||||||
llvm::OwningPtr<ExternalASTSource> Source;
|
llvm::OwningPtr<ExternalASTSource> Source;
|
||||||
|
|
||||||
if (!ImplicitIncludePCH.empty()) {
|
if (!ImplicitIncludePCH.empty()) {
|
||||||
Reader.reset(new PCHReader(PP, ContextOwner.get()));
|
// If the user specified -isysroot, it will be used for relocatable PCH
|
||||||
|
// files.
|
||||||
|
const char *isysrootPCH = 0;
|
||||||
|
if (isysroot.getNumOccurrences() != 0)
|
||||||
|
isysrootPCH = isysroot.c_str();
|
||||||
|
|
||||||
|
Reader.reset(new PCHReader(PP, ContextOwner.get(), isysrootPCH));
|
||||||
|
|
||||||
// The user has asked us to include a precompiled header. Load
|
// The user has asked us to include a precompiled header. Load
|
||||||
// the precompiled header into the AST context.
|
// the precompiled header into the AST context.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче