aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-10-16 23:40:58 +0000
committerDouglas Gregor <dgregor@apple.com>2012-10-16 23:40:58 +0000
commit57016dda61498294120b1a881d9e6606337b29d9 (patch)
tree5dfc64766b1250929020a9c1bba6347e84c1046b
parent708f69bcc1be715efd1e9f46266a9c1ead184be6 (diff)
Serialize TargetOptions into an AST file, and make sure that we keep
target options around so they can be accessed at any point (rather than keeping them transient). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166072 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td10
-rw-r--r--include/clang/Basic/TargetInfo.h4
-rw-r--r--include/clang/Basic/TargetOptions.h6
-rw-r--r--include/clang/Frontend/ASTUnit.h9
-rw-r--r--include/clang/Frontend/CompilerInvocation.h16
-rw-r--r--include/clang/Serialization/ASTReader.h14
-rw-r--r--lib/Basic/Targets.cpp12
-rw-r--r--lib/Frontend/ASTUnit.cpp32
-rw-r--r--lib/Frontend/CompilerInvocation.cpp14
-rw-r--r--lib/Serialization/ASTReader.cpp85
-rw-r--r--lib/Serialization/ASTWriter.cpp30
-rw-r--r--test/PCH/target-options.c5
-rw-r--r--test/PCH/target-options.h2
13 files changed, 156 insertions, 83 deletions
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index a440e806d7..435760bb87 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -25,9 +25,13 @@ def err_fe_pch_file_modified : Error<
def err_fe_pch_file_overridden : Error<
"file '%0' from the precompiled header has been overridden">;
-def warn_pch_target_triple : Error<
- "PCH file was compiled for the target '%0' but the current translation "
- "unit is being compiled for target '%1'">;
+def err_pch_targetopt_mismatch : Error<
+ "PCH file was compiled for the %0 '%1' but the current translation "
+ "unit is being compiled for target '%2'">;
+def err_pch_targetopt_feature_mismatch : Error<
+ "%select{AST file|current translation unit}0 was compiled with the target "
+ "feature'%1' but the %select{current translation unit is|AST file was}0 "
+ "not">;
def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "
"PCH file but is currently %select{disabled|enabled}2">;
def err_pch_langopt_value_mismatch : Error<
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 3e63505dfa..ea520e8f82 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -23,6 +23,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Support/DataTypes.h"
#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/VersionTuple.h"
#include "clang/Basic/Specifiers.h"
#include <cassert>
@@ -39,7 +40,6 @@ class LangOptions;
class MacroBuilder;
class SourceLocation;
class SourceManager;
-class TargetOptions;
namespace Builtin { struct Info; }
@@ -62,7 +62,7 @@ enum TargetCXXABI {
/// \brief Exposes information about the current target.
///
class TargetInfo : public RefCountedBase<TargetInfo> {
- TargetOptions *TargetOpts;
+ llvm::IntrusiveRefCntPtr<TargetOptions> TargetOpts;
llvm::Triple Triple;
protected:
// Target values set by the ctor of the actual target implementation. Default
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 15ececd1df..d6deb0244d 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -15,13 +15,14 @@
#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <string>
#include <vector>
namespace clang {
/// \brief Options for controlling the target.
-class TargetOptions {
+class TargetOptions : public RefCountedBase<TargetOptions> {
public:
/// If given, the name of the target triple to compile for. If not given the
/// target will be selected to match the host.
@@ -40,6 +41,9 @@ public:
/// If given, the version string of the linker in use.
std::string LinkerVersion;
+ /// \brief The list of target specific features to enable or disable, as written on the command line.
+ std::vector<std::string> FeaturesAsWritten;
+
/// The list of target specific features to enable or disable -- this should
/// be a list of strings starting with by '+' or '-'.
std::vector<std::string> Features;
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 0b02afa19d..c2bde120a0 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -71,8 +71,8 @@ private:
IntrusiveRefCntPtr<TargetInfo> Target;
IntrusiveRefCntPtr<Preprocessor> PP;
IntrusiveRefCntPtr<ASTContext> Ctx;
+ IntrusiveRefCntPtr<TargetOptions> TargetOpts;
ASTReader *Reader;
- TargetOptions TargetOpts;
struct ASTWriterData;
OwningPtr<ASTWriterData> WriterData;
@@ -91,13 +91,6 @@ private:
/// LoadFromCommandLine available.
IntrusiveRefCntPtr<CompilerInvocation> Invocation;
- /// \brief The set of target features.
- ///
- /// FIXME: each time we reparse, we need to restore the set of target
- /// features from this vector, because TargetInfo::CreateTargetInfo()
- /// mangles the target options in place. Yuck!
- std::vector<std::string> TargetFeatures;
-
// OnlyLocalDecls - when true, walking this AST should only visit declarations
// that come from the AST itself, not from included precompiled headers.
// FIXME: This is temporary; eventually, CIndex will always do this.
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 30c96cbb33..a58fef1f4b 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -52,6 +52,9 @@ class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
protected:
/// Options controlling the language variant.
IntrusiveRefCntPtr<LangOptions> LangOpts;
+
+ /// Options controlling the target.
+ IntrusiveRefCntPtr<TargetOptions> TargetOpts;
public:
CompilerInvocationBase();
@@ -59,6 +62,11 @@ public:
LangOptions *getLangOpts() { return LangOpts.getPtr(); }
const LangOptions *getLangOpts() const { return LangOpts.getPtr(); }
+
+ TargetOptions &getTargetOpts() { return *TargetOpts.getPtr(); }
+ const TargetOptions &getTargetOpts() const {
+ return *TargetOpts.getPtr();
+ }
};
/// \brief Helper class for holding the data necessary to invoke the compiler.
@@ -96,9 +104,6 @@ class CompilerInvocation : public CompilerInvocationBase {
/// Options controlling preprocessed output.
PreprocessorOutputOptions PreprocessorOutputOpts;
- /// Options controlling the target.
- TargetOptions TargetOpts;
-
public:
CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {}
@@ -199,11 +204,6 @@ public:
return PreprocessorOutputOpts;
}
- TargetOptions &getTargetOpts() { return TargetOpts; }
- const TargetOptions &getTargetOpts() const {
- return TargetOpts;
- }
-
/// @}
};
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index d23e7c5bf4..02e9927dbe 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -82,6 +82,7 @@ class ASTStmtReader;
class TypeLocReader;
struct HeaderFileInfo;
class VersionTuple;
+class TargetOptions;
struct PCHPredefinesBlock {
/// \brief The file ID for this predefines buffer in a PCH file.
@@ -110,11 +111,12 @@ public:
return false;
}
- /// \brief Receives the target triple.
+ /// \brief Receives the target options.
///
- /// \returns true to indicate the target triple is invalid or false otherwise.
- virtual bool ReadTargetTriple(const serialization::ModuleFile &M,
- StringRef Triple) {
+ /// \returns true to indicate the target options are invalid, or false
+ /// otherwise.
+ virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
+ const TargetOptions &TargetOpts) {
return false;
}
@@ -158,8 +160,8 @@ public:
virtual bool ReadLanguageOptions(const serialization::ModuleFile &M,
const LangOptions &LangOpts);
- virtual bool ReadTargetTriple(const serialization::ModuleFile &M,
- StringRef Triple);
+ virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
+ const TargetOptions &TargetOpts);
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
StringRef OriginalFileName,
std::string &SuggestedPredefines,
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 2e6678bb89..cd835023ab 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -4635,8 +4635,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
// Apply the user specified deltas.
// First the enables.
- for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
- ie = Opts.Features.end(); it != ie; ++it) {
+ for (std::vector<std::string>::const_iterator
+ it = Opts.FeaturesAsWritten.begin(),
+ ie = Opts.FeaturesAsWritten.end();
+ it != ie; ++it) {
const char *Name = it->c_str();
if (Name[0] != '+')
@@ -4650,8 +4652,10 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
}
// Then the disables.
- for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
- ie = Opts.Features.end(); it != ie; ++it) {
+ for (std::vector<std::string>::const_iterator
+ it = Opts.FeaturesAsWritten.begin(),
+ ie = Opts.FeaturesAsWritten.end();
+ it != ie; ++it) {
const char *Name = it->c_str();
if (Name[0] == '+')
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index e602d30374..bf78ac51ec 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -503,7 +503,7 @@ class ASTInfoCollector : public ASTReaderListener {
ASTContext &Context;
LangOptions &LangOpt;
HeaderSearch &HSI;
- TargetOptions &TargetOpts;
+ IntrusiveRefCntPtr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target;
std::string &Predefines;
unsigned &Counter;
@@ -513,7 +513,8 @@ class ASTInfoCollector : public ASTReaderListener {
bool InitializedLanguage;
public:
ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
- HeaderSearch &HSI, TargetOptions &TargetOpts,
+ HeaderSearch &HSI,
+ IntrusiveRefCntPtr<TargetOptions> &TargetOpts,
IntrusiveRefCntPtr<TargetInfo> &Target,
std::string &Predefines,
unsigned &Counter)
@@ -536,21 +537,18 @@ public:
return false;
}
- virtual bool ReadTargetTriple(const serialization::ModuleFile &M,
- StringRef Triple) {
+ virtual bool ReadTargetOptions(const serialization::ModuleFile &M,
+ const TargetOptions &TargetOpts) {
// If we've already initialized the target, don't do it again.
if (Target)
return false;
assert(M.Kind == serialization::MK_MainFile);
- // FIXME: This is broken, we should store the TargetOptions in the AST file.
- TargetOpts.ABI = "";
- TargetOpts.CXXABI = "";
- TargetOpts.CPU = "";
- TargetOpts.Features.clear();
- TargetOpts.Triple = Triple;
- Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
+
+ this->TargetOpts = new TargetOptions(TargetOpts);
+ Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(),
+ *this->TargetOpts);
updated();
return false;
@@ -1098,7 +1096,6 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
@@ -1568,9 +1565,8 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
- Clang->getTargetOpts()));
+ Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
Preamble.clear();
@@ -1777,9 +1773,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
CI->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
- // Save the target features.
- AST->TargetFeatures = CI->getTargetOpts().Features;
-
// Create the compiler instance to use for building the AST.
OwningPtr<CompilerInstance> Clang(new CompilerInstance());
@@ -1795,7 +1788,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
Clang->setDiagnostics(&AST->getDiagnostics());
// Create the target instance.
- Clang->getTargetOpts().Features = AST->TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts()));
if (!Clang->hasTarget())
@@ -1884,9 +1876,6 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
Invocation->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
- // Save the target features.
- TargetFeatures = Invocation->getTargetOpts().Features;
-
llvm::MemoryBuffer *OverrideMainBuffer = 0;
if (PrecompilePreamble) {
PreambleRebuildCounter = 2;
@@ -2396,7 +2385,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
StoredDiagnostics);
// Create the target instance.
- Clang->getTargetOpts().Features = TargetFeatures;
Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Clang->getTargetOpts()));
if (!Clang->hasTarget()) {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6d34425e13..5fc3f1bd18 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -35,11 +35,12 @@ using namespace clang;
//===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase()
- : LangOpts(new LangOptions()) {}
+ : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
: RefCountedBase<CompilerInvocation>(),
- LangOpts(new LangOptions(*X.getLangOpts())) {}
+ LangOpts(new LangOptions(*X.getLangOpts())),
+ TargetOpts(new TargetOptions(X.getTargetOpts())) {}
//===----------------------------------------------------------------------===//
// Utility functions.
@@ -927,8 +928,8 @@ static void TargetOptsToArgs(const TargetOptions &Opts,
Res.push_back("-target-linker-version", Opts.LinkerVersion);
if (!Opts.CXXABI.empty())
Res.push_back("-cxx-abi", Opts.CXXABI);
- for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i)
- Res.push_back("-target-feature", Opts.Features[i]);
+ for (unsigned i = 0, e = Opts.FeaturesAsWritten.size(); i != e; ++i)
+ Res.push_back("-target-feature", Opts.FeaturesAsWritten[i]);
}
void CompilerInvocation::toArgs(std::vector<std::string> &Res) const {
@@ -2285,7 +2286,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
- Opts.Features = Args.getAllArgValues(OPT_target_feature);
+ Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
@@ -2431,7 +2432,8 @@ std::string CompilerInvocation::getModuleHash() const {
#include "clang/Basic/LangOptions.def"
// Extend the signature with the target triple
- llvm::Triple T(TargetOpts.Triple);
+ // FIXME: Add target options.
+ llvm::Triple T(TargetOpts->Triple);
Signature.add((unsigned)T.getArch(), 5);
Signature.add((unsigned)T.getVendor(), 4);
Signature.add((unsigned)T.getOS(), 5);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index a62f2578e9..67a54caf64 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -37,6 +37,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/StringExtras.h"
@@ -101,13 +102,66 @@ PCHValidator::ReadLanguageOptions(const ModuleFile &M,
return false;
}
-bool PCHValidator::ReadTargetTriple(const ModuleFile &M, StringRef Triple) {
- if (Triple == PP.getTargetInfo().getTriple().str())
- return false;
+bool PCHValidator::ReadTargetOptions(const ModuleFile &M,
+ const TargetOptions &TargetOpts) {
+ const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
+
+#define CHECK_TARGET_OPT(Field, Name) \
+ if (TargetOpts.Field != ExistingTargetOpts.Field) { \
+ Reader.Diag(diag::err_pch_targetopt_mismatch) \
+ << Name << TargetOpts.Field << ExistingTargetOpts.Field; \
+ return true; \
+ }
+
+ CHECK_TARGET_OPT(Triple, "target");
+ CHECK_TARGET_OPT(CPU, "target CPU");
+ CHECK_TARGET_OPT(ABI, "target ABI");
+ CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
+ CHECK_TARGET_OPT(LinkerVersion, "target linker version");
+#undef CHECK_TARGET_OPT
+
+ // Compare feature sets.
+ SmallVector<StringRef, 4> ExistingFeatures(
+ ExistingTargetOpts.FeaturesAsWritten.begin(),
+ ExistingTargetOpts.FeaturesAsWritten.end());
+ SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
+ TargetOpts.FeaturesAsWritten.end());
+ std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
+ std::sort(ReadFeatures.begin(), ReadFeatures.end());
+
+ unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
+ unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
+ while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
+ if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
+ ++ExistingIdx;
+ ++ReadIdx;
+ continue;
+ }
+
+ if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
+ Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
+ << false << ReadFeatures[ReadIdx];
+ return true;
+ }
- Reader.Diag(diag::warn_pch_target_triple)
- << Triple << PP.getTargetInfo().getTriple().str();
- return true;
+ Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
+ << true << ExistingFeatures[ExistingIdx];
+ return true;
+ }
+
+ if (ExistingIdx < ExistingN) {
+ Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
+ << true << ExistingFeatures[ExistingIdx];
+ return true;
+ }
+
+ if (ReadIdx < ReadN) {
+ Reader.Diag(diag::err_pch_targetopt_feature_mismatch)
+ << false << ReadFeatures[ReadIdx];
+ return true;
+ }
+
+ return false;
}
namespace {
@@ -1834,7 +1888,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case METADATA: {
if (Record[0] != VERSION_MAJOR && !DisableValidation) {
Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
- : diag::warn_pch_version_too_new);
+ : diag::warn_pch_version_too_new);
return IgnorePCH;
}
@@ -1846,8 +1900,21 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
RelocatablePCH = Record[4];
if (Listener) {
- std::string TargetTriple(BlobStart, BlobLen);
- if (Listener->ReadTargetTriple(F, TargetTriple))
+ unsigned Idx = 6;
+ TargetOptions TargetOpts;
+ TargetOpts.Triple = ReadString(Record, Idx);
+ TargetOpts.CPU = ReadString(Record, Idx);
+ TargetOpts.ABI = ReadString(Record, Idx);
+ TargetOpts.CXXABI = ReadString(Record, Idx);
+ TargetOpts.LinkerVersion = ReadString(Record, Idx);
+ for (unsigned N = Record[Idx++]; N; --N) {
+ TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
+ }
+ for (unsigned N = Record[Idx++]; N; --N) {
+ TargetOpts.Features.push_back(ReadString(Record, Idx));
+ }
+
+ if (Listener->ReadTargetOptions(F, TargetOpts))
return IgnorePCH;
}
break;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index d04753a037..c37f881d98 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -35,6 +35,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/APFloat.h"
@@ -984,27 +985,28 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot,
// Metadata
const TargetInfo &Target = Context.getTargetInfo();
- BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
- MetaAbbrev->Add(BitCodeAbbrevOp(METADATA));
- MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major
- MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST 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::Fixed, 1)); // Has errors
- MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple
- unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
-
+ const TargetOptions &TargetOpts = Target.getTargetOpts();
RecordData Record;
- Record.push_back(METADATA);
Record.push_back(VERSION_MAJOR);
Record.push_back(VERSION_MINOR);
Record.push_back(CLANG_VERSION_MAJOR);
Record.push_back(CLANG_VERSION_MINOR);
Record.push_back(!isysroot.empty());
Record.push_back(ASTHasCompilerErrors);
- const std::string &Triple = Target.getTriple().getTriple();
- Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple);
+ AddString(TargetOpts.Triple, Record);
+ AddString(TargetOpts.CPU, Record);
+ AddString(TargetOpts.ABI, Record);
+ AddString(TargetOpts.CXXABI, Record);
+ AddString(TargetOpts.LinkerVersion, Record);
+ Record.push_back(TargetOpts.FeaturesAsWritten.size());
+ for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {
+ AddString(TargetOpts.FeaturesAsWritten[I], Record);
+ }
+ Record.push_back(TargetOpts.Features.size());
+ for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) {
+ AddString(TargetOpts.Features[I], Record);
+ }
+ Stream.EmitRecord(METADATA, Record);
if (Chain) {
serialization::ModuleManager &Mgr = Chain->getModuleManager();
diff --git a/test/PCH/target-options.c b/test/PCH/target-options.c
new file mode 100644
index 0000000000..2b85efe07a
--- /dev/null
+++ b/test/PCH/target-options.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin9 -emit-pch -o %t.pch %S/target-options.h
+// RUN: not %clang_cc1 -triple=x86_64-unknown-freebsd7.0 -include-pch %t.pch %s -emit-llvm -o - > %t.err 2>&1
+// RUN: FileCheck %s < %t.err
+
+// CHECK: for the target
diff --git a/test/PCH/target-options.h b/test/PCH/target-options.h
new file mode 100644
index 0000000000..2c3edf6aa2
--- /dev/null
+++ b/test/PCH/target-options.h
@@ -0,0 +1,2 @@
+enum { apple_cc = __APPLE_CC__ };
+