Index: clang/include/clang/Basic/MacroBuilder.h
===================================================================
--- clang.orig/include/clang/Basic/MacroBuilder.h	2011-12-02 11:13:45.509899300 +1000
+++ clang/include/clang/Basic/MacroBuilder.h	2011-12-02 11:14:07.577428400 +1000
@@ -35,6 +35,25 @@
     Out << "#undef " << Name << '\n';
   }
 
+  /// Append an #assert line for an assertion of the form
+  /// "#assert Predicate(Value)\n".
+  void assertValue(const llvm::Twine &Predicate, const llvm::Twine &Value) {
+    Out << "#assert " << Predicate << '(' << Value << ")\n";
+  }
+
+  /// Append an #unassert line for an unassert of the form
+  /// "#unassert Predicate(Value)\n".
+  void unassertValue(const llvm::Twine &Predicate, const llvm::Twine &Value) {
+    Out << "#unassert " << Predicate << '(' << Value << ")\n";
+  }
+
+  /// Append an #unassert line for an assertion of the form
+  /// "#unassert Predicate\n" which will unassert all the value for the
+  /// specified predicate.
+  void unassertPredicate(const llvm::Twine &Predicate) {
+    Out << "#unassert " << Predicate << '\n';
+  }
+
   /// Directly append Str and a newline to the underlying buffer.
   void append(const Twine &Str) {
     Out << Str << '\n';
Index: clang/lib/Basic/Targets.cpp
===================================================================
--- clang.orig/lib/Basic/Targets.cpp	2011-12-02 11:13:45.519899300 +1000
+++ clang/lib/Basic/Targets.cpp	2011-12-02 11:14:07.617433500 +1000
@@ -233,6 +233,8 @@
     Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
     Builder.defineMacro("__tune_i386__");
     DefineStd(Builder, "unix", Opts);
+    Builder.assertValue("system", "bsd");
+    Builder.assertValue("system", "unix");
   }
 public:
   DragonFlyBSDTargetInfo(const std::string &triple)
@@ -256,6 +258,8 @@
     Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
     DefineStd(Builder, "unix", Opts);
     Builder.defineMacro("__ELF__");
+    Builder.assertValue("system", "bsd");
+    Builder.assertValue("system", "unix");
   }
 public:
   FreeBSDTargetInfo(const std::string &triple)
@@ -299,6 +303,7 @@
     Builder.defineMacro("_EM_FSIZE", "4");
     Builder.defineMacro("_EM_DSIZE", "8");
     DefineStd(Builder, "unix", Opts);
+    Builder.assertValue("system", "unix");
   }
 public:
   MinixTargetInfo(const std::string &triple)
@@ -316,6 +321,7 @@
     // Linux defines; list based off of gcc output
     DefineStd(Builder, "unix", Opts);
     DefineStd(Builder, "linux", Opts);
+    Builder.assertValue("system", "unix");
     Builder.defineMacro("__gnu_linux__");
     Builder.defineMacro("__ELF__");
     if (Opts.POSIXThreads)
@@ -347,6 +353,8 @@
     Builder.defineMacro("__ELF__");
     if (Opts.POSIXThreads)
       Builder.defineMacro("_POSIX_THREADS");
+    Builder.assertValue("system", "bsd");
+    Builder.assertValue("system", "unix");
   }
 public:
   NetBSDTargetInfo(const std::string &triple)
@@ -368,6 +376,8 @@
     Builder.defineMacro("__ELF__");
     if (Opts.POSIXThreads)
       Builder.defineMacro("_POSIX_THREADS");
+    Builder.assertValue("system", "bsd");
+    Builder.assertValue("system", "unix");
   }
 public:
   OpenBSDTargetInfo(const std::string &triple)
@@ -451,6 +461,8 @@
     Builder.defineMacro("__ELF__");
     Builder.defineMacro("__svr4__");
     Builder.defineMacro("__SVR4");
+    Builder.assertValue("system", "svr4");
+    Builder.assertValue("system", "unix");
   }
 public:
   AuroraUXTargetInfo(const std::string& triple)
@@ -472,6 +484,9 @@
     Builder.defineMacro("__ELF__");
     Builder.defineMacro("__svr4__");
     Builder.defineMacro("__SVR4");
+    Builder.assertValue("system", "svr4");
+    Builder.assertValue("system", "unix");
+    Builder.assertValue("system", "sun");
   }
 public:
   SolarisTargetInfo(const std::string& triple)
@@ -686,6 +701,7 @@
   } else {
     Builder.defineMacro("__ppc__");
   }
+  Builder.assertValue("cpu", "ppc");
 
   // Target properties.
   if (getTriple().getOS() != llvm::Triple::NetBSD)
@@ -1718,6 +1734,7 @@
   } else {
     DefineStd(Builder, "i386", Opts);
   }
+  Builder.assertValue("cpu", "i386");
 
   // Subtarget options.
   // FIXME: We are hard-coding the tune parameters based on the CPU, but they
@@ -2145,6 +2162,7 @@
     Builder.defineMacro("__CYGWIN__");
     Builder.defineMacro("__CYGWIN32__");
     DefineStd(Builder, "unix", Opts);
+    Builder.assertValue("system", "unix");
     if (Opts.CPlusPlus)
       Builder.defineMacro("_GNU_SOURCE");
   }
@@ -2567,6 +2585,7 @@
     // Target identification.
     Builder.defineMacro("__arm");
     Builder.defineMacro("__arm__");
+    Builder.assertValue("cpu", "arm");
 
     // Target properties.
     Builder.defineMacro("__ARMEL__");
@@ -2792,6 +2811,7 @@
   virtual void getTargetDefines(const LangOptions &Opts,
                                 MacroBuilder &Builder) const {
     DefineStd(Builder, "sparc", Opts);
+    Builder.assertValue("cpu", "sparc");
     Builder.defineMacro("__sparcv8");
     Builder.defineMacro("__REGISTER_PREFIX__", "");
 
@@ -3117,6 +3137,7 @@
   }
   virtual void getArchDefines(const LangOptions &Opts,
                               MacroBuilder &Builder) const {
+    Builder.assertValue("cpu", "mips");
     Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
     Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
     Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
@@ -3232,6 +3253,7 @@
   }
   virtual void getArchDefines(const LangOptions &Opts,
                               MacroBuilder &Builder) const {
+    Builder.assertValue("cpu", "mips");
     if (ABI == "n32") {
       Builder.defineMacro("__mips_n32");
       Builder.defineMacro("_ABIN32", "2");
Index: clang/test/Preprocessor/assertion_predef.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/test/Preprocessor/assertion_predef.c	2011-12-02 11:17:35.274302600 +1000
@@ -0,0 +1,59 @@
+// the features tested here are for compatibility with ancient versions of GCC
+// the specification of which assertions should be asserted on any given machine and OS
+// are poorly documented. The tests here try to reflect the details shown in the GCC
+// 2.95 release notes which were found at http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC37
+
+// RUN: %clang_cc1 -triple i686-pc-win32 -E %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_I386
+// CHECK_I386: I386
+#if #cpu(i386)
+I386
+#endif
+
+// RUN: %clang_cc1 -triple sparc-sun-solaris2.10 -E %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_SPARC
+// CHECK_SPARC: SPARC
+// CHECK_SPARC: SVR4
+// CHECK_SPARC: SUN
+// CHECK_SPARC: UNIX
+#if #cpu(sparc)
+SPARC
+#endif
+
+#if #system(svr4)
+SVR4
+#endif
+
+#if #system(sun)
+SUN
+#endif
+
+#if #system(unix)
+UNIX
+#endif
+
+// RUN: %clang_cc1 -triple powerpc-apple-darwin9 -E %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_PPC
+// CHECK_PPC: PPC
+#if #cpu(ppc)
+PPC
+#endif
+
+// RUN: %clang_cc1 -triple arm-unknown-linux-gnu -E %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_ARM
+// CHECK_ARM: ARM
+#if #cpu(arm)
+ARM
+#endif
+
+// RUN: %clang_cc1 -triple mips-unknown-linux-gnu -E %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_MIPS
+// CHECK_MIPS: MIPS
+#if #cpu(mips)
+MIPS
+#endif
+
+// RUN: %clang_cc1 -triple i686-pc-freebsd -E %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_BSD
+// CHECK_BSD: BSD
+// CHECK_BSD: UNIX
+#if #system(bsd)
+BSD
+#endif
+#if #system(unix)
+UNIX
+#endif