Serialize TargetOptions into an AST file, and make sure that we keep
authorDouglas Gregor <dgregor@apple.com>
Tue, 16 Oct 2012 23:40:58 +0000 (23:40 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 16 Oct 2012 23:40:58 +0000 (23:40 +0000)
target options around so they can be accessed at any point (rather
than keeping them transient).

llvm-svn: 166072

13 files changed:
clang/include/clang/Basic/DiagnosticSerializationKinds.td
clang/include/clang/Basic/TargetInfo.h
clang/include/clang/Basic/TargetOptions.h
clang/include/clang/Frontend/ASTUnit.h
clang/include/clang/Frontend/CompilerInvocation.h
clang/include/clang/Serialization/ASTReader.h
clang/lib/Basic/Targets.cpp
clang/lib/Frontend/ASTUnit.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/PCH/target-options.c [new file with mode: 0644]
clang/test/PCH/target-options.h [new file with mode: 0644]

index a440e80..435760b 100644 (file)
@@ -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<
index 3e63505..ea520e8 100644 (file)
@@ -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
index 15ececd..d6deb02 100644 (file)
 #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;
index 0b02afa..c2bde12 100644 (file)
@@ -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.
index 30c96cb..a58fef1 100644 (file)
@@ -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;
-  }
-
   /// @}
 };
 
index d23e7c5..02e9927 100644 (file)
@@ -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,
index 2e6678b..cd83502 100644 (file)
@@ -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] == '+')
index e602d30..bf78ac5 100644 (file)
@@ -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()) {
index 6d34425..5fc3f1b 100644 (file)
@@ -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);
index a62f257..67a54ca 100644 (file)
@@ -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;
index d04753a..c37f881 100644 (file)
@@ -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/clang/test/PCH/target-options.c b/clang/test/PCH/target-options.c
new file mode 100644 (file)
index 0000000..2b85efe
--- /dev/null
@@ -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/clang/test/PCH/target-options.h b/clang/test/PCH/target-options.h
new file mode 100644 (file)
index 0000000..2c3edf6
--- /dev/null
@@ -0,0 +1,2 @@
+enum { apple_cc = __APPLE_CC__ };
+