Index: clang/include/clang/Basic/DiagnosticLexKinds.td
===================================================================
--- clang.orig/include/clang/Basic/DiagnosticLexKinds.td	2011-11-30 11:39:10.000000000 +1000
+++ clang/include/clang/Basic/DiagnosticLexKinds.td	2011-11-30 12:27:25.411732100 +1000
@@ -232,6 +232,8 @@
   "expected comma in macro parameter list">;
 def err_pp_duplicate_name_in_arg_list : Error<
   "duplicate macro parameter name %0">;
+def err_pp_predicate_not_identifier : Error<"assertion predicates must be identifiers">;
+def err_pp_missing_assert_predicate : Error<"assertion predicate missing">;
 def err_pp_stringize_not_parameter : Error<
   "'#' is not followed by a macro parameter">;
 def err_pp_malformed_ident : Error<"invalid #ident directive">;
@@ -320,6 +322,7 @@
 
 def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
 def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
+def err_assert_predicate_name : Error<"'assert' cannot be used as an assertion predicate">;
 def err_paste_at_start : Error<
   "'##' cannot appear at start of macro expansion">;
 def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">;
@@ -338,6 +341,8 @@
   InGroup<DiagGroup<"invalid-token-paste">>;
 def err_pp_operator_used_as_macro_name : Error<
   "C++ operator '%0' cannot be used as a macro name">;
+def err_pp_operator_used_as_assert_predicate : Error<
+  "C++ operator '%0' cannot be used as an assertion predicate">;
 def err_pp_illegal_floating_literal : Error<
   "floating point literal in preprocessor expression">;
 def err_pp_line_requires_integer : Error<
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang.orig/include/clang/Lex/Preprocessor.h	2011-11-30 11:39:19.000000000 +1000
+++ clang/include/clang/Lex/Preprocessor.h	2011-12-02 12:23:53.246940900 +1000
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_LEX_PREPROCESSOR_H
 
 #include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/AssertionInfo.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/PTHLexer.h"
 #include "clang/Lex/PPCallbacks.h"
@@ -240,6 +241,10 @@
   /// to the actual definition of the macro.
   llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros;
 
+  /// Assertions - For each IdentifierInfo that has appeared as an asserted
+  /// predicate, we store the values for which it was asserted
+  llvm::DenseMap<IdentifierInfo*, std::vector<AssertionInfo*> > AssertedValues;
+
   /// \brief Macros that we want to warn because they are not used at the end
   /// of the translation unit; we store just their SourceLocations instead
   /// something like MacroInfo*. The benefit of this is that when we are
@@ -326,6 +331,20 @@
 
   MacroInfo *getInfoForMacro(IdentifierInfo *II) const;
 
+  struct AssertionInfoChain {
+    AssertionInfo AI;
+    AssertionInfoChain *Next;
+    AssertionInfoChain *Prev;
+  };
+
+  /// AIChainHead - AssertionInfo objects are managed as a chain for easy
+  /// disposal. This is the head of that list.
+  AssertionInfoChain *AIChainHead;
+
+  /// AICache - A "freelist" of AssertionInfo objects that can be reused for
+  /// quick allocation.
+  AssertionInfoChain *AICache;
+
 public:
   Preprocessor(DiagnosticsEngine &diags, LangOptions &opts,
                const TargetInfo *target,
@@ -440,6 +459,30 @@
   macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
   macro_iterator macro_end(bool IncludeExternalMacros = true) const;
 
+  /// AddAssertionValue - assert the specified identifier to the
+  /// set of asserted values for the given assertion key
+  void AddAssertionValue(IdentifierInfo *II, AssertionInfo *AI);
+
+  /// IsAsserted - test if the specified identifier has been asserted as a
+  /// value of the given assertion key returns true iff it has
+  bool IsAsserted(IdentifierInfo *II, AssertionInfo *AI);
+
+  /// RemoveAssertionValue - remove the specified identifier from the set of
+  /// asserted values for the given assertion key
+  void RemoveAssertionValue(IdentifierInfo *II, AssertionInfo *AI);
+
+  /// RemoveAssertion - remove the specified assertion and all of its asserted
+  /// values
+  void RemoveAssertion(IdentifierInfo *II);
+
+  /// assertion_iterator/assertion_begin/assertion_end - This allows you to
+  /// walk the current state of the assertions table. This visits every
+  /// currently asserted predicate
+  typedef llvm::DenseMap<IdentifierInfo*,
+              std::vector<AssertionInfo*> >::const_iterator assertion_iterator;
+  assertion_iterator assertion_begin() const;
+  assertion_iterator assertion_end() const;
+
   const std::string &getPredefines() const { return Predefines; }
   /// setPredefines - Set the predefines for this Preprocessor.  These
   /// predefines are automatically injected when parsing the main file.
@@ -985,6 +1028,10 @@
   unsigned getCounterValue() const { return CounterValue; }
   void setCounterValue(unsigned V) { CounterValue = V; }
 
+  /// AllocateAssertionInfo - Allocate a new AssertionInfo object with the
+  /// provided SourceLocation.
+  AssertionInfo *AllocateAssertionInfo(SourceLocation L);
+
   /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide
   ///  SourceLocation.
   MacroInfo *AllocateMacroInfo(SourceLocation L);
@@ -1077,6 +1124,30 @@
   /// parsing the arg list.
   bool ReadMacroDefinitionArgList(MacroInfo *MI);
 
+  /// AllocateAssertionInfo - Allocate a new AssertionInfo object, possibly
+  /// recycling previously unallocated AssertionInfo objects
+  AssertionInfo *AllocateAssertionInfo();
+
+public:
+  /// ReleaseAssertionInfo - Release the specified AssertionInfo. This memory
+  /// will be reused for allocating new AssertionInfo objects
+  void ReleaseAssertionInfo(AssertionInfo *AI);
+
+private:
+  /// ReadAssertionPredicate - Lex and validate an assertion name, which occurs
+  /// an #assert or #unassert. This emits a diagnostic, sets the token kind to
+  /// eod, and discards the rest of the assertion line if the predicate is
+  /// invalid.
+  void ReadAssertionPredicate(Token &AssertionPredicateTok,
+                              char isAssertUnassert = 0);
+
+  /// ReadAssertionValue - Lex and validate an assertion value, which occurs in
+  /// parentheses after an #assert or #unassert and its predicate. This
+  /// function handles lexing the open and close parens and validates them.
+  /// This emits a diagnostic, sets the token kind to eod, and discards the
+  /// rest of the assertion line if the predicate is invalid.
+  void ReadAssertionValue(Token &Tok, AssertionInfo *AI);
+
   /// SkipExcludedConditionalBlock - We just read a #if or related directive and
   /// decided that the subsequent tokens are in the #if'd out portion of the
   /// file.  Lex the rest of the file, until we see an #endif.  If
@@ -1208,6 +1279,10 @@
   void HandleDefineDirective(Token &Tok);
   void HandleUndefDirective(Token &Tok);
 
+  // Assertion handling.
+  void HandleAssertDirective(Token &Tok);
+  void HandleUnassertDirective(Token &Tok);
+
   // Conditional Inclusion.
   void HandleIfdefDirective(Token &Tok, bool isIfndef,
                             bool ReadAnyTokensBeforeDirective);
Index: clang/lib/Lex/CMakeLists.txt
===================================================================
--- clang.orig/lib/Lex/CMakeLists.txt	2011-11-30 11:39:59.000000000 +1000
+++ clang/lib/Lex/CMakeLists.txt	2011-11-30 12:27:25.452737300 +1000
@@ -11,6 +11,8 @@
   LiteralSupport.cpp
   MacroArgs.cpp
   MacroInfo.cpp
+  AssertionInfo.cpp
+  PPAssertionHandler.cpp
   ModuleMap.cpp
   PPCaching.cpp
   PPDirectives.cpp
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang.orig/lib/Lex/PPDirectives.cpp	2011-11-30 11:39:27.000000000 +1000
+++ clang/lib/Lex/PPDirectives.cpp	2011-12-01 15:52:33.907093800 +1000
@@ -81,6 +81,53 @@
   MI->Destroy();
 }
 
+AssertionInfo *Preprocessor::AllocateAssertionInfo() {
+  AssertionInfoChain *AIChain;
+
+  if (AICache) {
+    AIChain = AICache;
+    AICache = AICache->Next;
+  } else {
+    AIChain = BP.Allocate<AssertionInfoChain>();
+  }
+
+  AIChain->Next = AIChainHead;
+  AIChain->Prev = 0;
+  if (AIChainHead)
+    AIChainHead->Prev = AIChain;
+  AIChainHead = AIChain;
+
+  return &(AIChain->AI);
+}
+
+AssertionInfo *Preprocessor::AllocateAssertionInfo(SourceLocation L) {
+  AssertionInfo *AI = AllocateAssertionInfo();
+  new (AI) AssertionInfo(L);
+  return AI;
+}
+
+/// ReleaseMacroInfo - Release the specified AssertionInfo. This memory will be
+/// reused for allocating new AssertionInfo objects.
+void Preprocessor::ReleaseAssertionInfo(AssertionInfo *AI) {
+  AssertionInfoChain *AIChain = (AssertionInfoChain*)AI;
+  if (AssertionInfoChain *Prev = AIChain->Prev) {
+    AssertionInfoChain *Next = AIChain->Next;
+    Prev->Next = Next;
+    if (Next) {
+      Next->Prev = Prev;
+    }
+  } else {
+    assert(AIChainHead == AIChain);
+    AIChainHead = AIChain->Next;
+    if (AIChainHead)
+      AIChainHead->Prev = 0;
+  }
+  AIChain->Next = AICache;
+  AICache = AIChain;
+
+  AI->Destory();
+}
+
 /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
 /// current line until the tok::eod token is found.
 void Preprocessor::DiscardUntilEndOfDirective() {
@@ -91,6 +138,53 @@
   } while (Tmp.isNot(tok::eod));
 }
 
+/// ReadAssertionPredicate - Lex and validate an assertion predicate, which
+/// occurs after an #assert or #unassert. This sets the token kind to eod and
+/// discards the rest of the line if the assert is invalid.
+/// isAssertUnassert is 1 if this is due to an #assert, 2 if #unassert
+/// directive, 0 if it is something else
+void Preprocessor::ReadAssertionPredicate(Token &AssertionPredTok,
+    char isAssertUnassert) {
+  //Read the token, don't allow macro expansion on it
+  LexUnexpandedToken(AssertionPredTok);
+
+  // Missing assertion predicate?
+  if (AssertionPredTok.is(tok::eod)) {
+    Diag(AssertionPredTok, diag::err_pp_missing_assert_predicate);
+    return;
+  }
+
+  IdentifierInfo *II = AssertionPredTok.getIdentifierInfo();
+  if (II == 0) {
+    bool Invalid = false;
+    std::string Spelling = getSpelling(AssertionPredTok, &Invalid);
+    if (Invalid) {
+      return;
+    }
+
+    const IdentifierInfo &Info = Identifiers.get(Spelling);
+    if (Info.isCPlusPlusOperatorKeyword()) {
+      Diag(AssertionPredTok, diag::err_pp_operator_used_as_assert_predicate)
+        << Spelling;
+    } else {
+      Diag(AssertionPredTok, diag::err_pp_predicate_not_identifier);
+    }
+    // Fall through on error.
+  } else if (isAssertUnassert && II->getPPKeywordID() == tok::pp_assert) {
+    // Error if using assert as a predicate since using it would require
+    // #assert
+    Diag(AssertionPredTok, diag::err_assert_predicate_name);
+  } else {
+    // Okay, we got a good identifier node. Return it.
+    return;
+  }
+
+  // Invalid name, read and discard the rest of the line. Then set the token
+  // kind to tok::eod
+  AssertionPredTok.setKind(tok::eod);
+  return DiscardUntilEndOfDirective();
+}
+
 /// ReadMacroName - Lex and validate a macro name, which occurs after a
 /// #define or #undef.  This sets the token kind to eod and discards the rest
 /// of the macro line if the macro name is invalid.  isDefineUndef is 1 if
@@ -659,11 +753,9 @@
     case tok::pp_sccs:
       return HandleIdentSCCSDirective(Result);
     case tok::pp_assert:
-      //isExtension = true;  // FIXME: implement #assert
-      break;
+      return HandleAssertDirective(Result);
     case tok::pp_unassert:
-      //isExtension = true;  // FIXME: implement #unassert
-      break;
+      return HandleUnassertDirective(Result);
         
     case tok::pp___export_macro__:
       return HandleMacroExportDirective(Result);
@@ -1739,6 +1831,104 @@
   setMacroInfo(MacroNameTok.getIdentifierInfo(), 0);
 }
 
+//===----------------------------------------------------------------------===//
+// Preprocessor Assertion Directive Handling.
+//===----------------------------------------------------------------------===//
+void Preprocessor::HandleAssertDirective(Token &DTok) {
+  Token AssertionPredicateTok;
+  ReadAssertionPredicate(AssertionPredicateTok, 1);
+
+  if (AssertionPredicateTok.is(tok::eod)) {
+    return;
+  }
+
+  AssertionInfo *AI =
+    AllocateAssertionInfo(AssertionPredicateTok.getLocation());
+  Token Tok;
+  LexUnexpandedToken(Tok);
+  ReadAssertionValue(Tok, AI);
+
+  // add to AI
+  if (AI != 0) {
+    // FIXME: Provide a callback here
+    AddAssertionValue(AssertionPredicateTok.getIdentifierInfo(), AI);
+  }
+}
+
+void Preprocessor::HandleUnassertDirective(Token &DTok) {
+  Token AssertionPredicateTok;
+  ReadAssertionPredicate(AssertionPredicateTok, 2);
+
+  // check to see if we read eod which indicates an error has occurred and
+  // an appropriate diagnostic has already been generated
+  if (AssertionPredicateTok.is(tok::eod)) {
+    return;
+  }
+
+  Token Tok;
+  LexUnexpandedToken(Tok);
+
+  IdentifierInfo *II = AssertionPredicateTok.getIdentifierInfo();
+
+  // we have a valid identifier so we need to create an AssertionInfo to hold
+  // the value to associate with the predicate
+  assertion_iterator iter = AssertedValues.find(II);
+
+  // we don't have an entry in the assertion table for the predicate, this is a
+  // noop so escape early
+  if (iter == assertion_end()) {
+    return;
+  }
+
+  if (Tok.is(tok::eod)) {
+    // FIXME: provide a callback here
+    RemoveAssertion(II);
+  } else {
+    // FIXME: provide a callback here
+
+    AssertionInfo *AI = AllocateAssertionInfo(
+      AssertionPredicateTok.getLocation());
+    ReadAssertionValue(Tok, AI);
+
+    if (AI != 0) {
+      RemoveAssertionValue(II, AI);
+    }
+  }
+}
+
+void Preprocessor::ReadAssertionValue(Token &Tok, AssertionInfo *AI) {
+  if (Tok.isNot(tok::l_paren)) {
+    // emit diag
+    ReleaseAssertionInfo(AI);
+    AI = 0;
+    return DiscardUntilEndOfDirective();
+  }
+
+  while (true) {
+    LexUnexpandedToken(Tok);
+    if (Tok.is(tok::r_paren) || Tok.is(tok::eod)) {
+      break;
+    }
+    AI->AddToken(Tok);
+  }
+
+  // check for the closing ), if we don't have it relase the AssetionInfo and
+  // discard the rest of the directive
+  if (!Tok.is(tok::r_paren)) {
+    ReleaseAssertionInfo(AI);
+    AI = 0;
+    return DiscardUntilEndOfDirective();
+  }
+
+  // check there is nothing after the closing ), if we have anything release
+  // the Assertioninfo and idscard the rest of the directive
+  LexUnexpandedToken(Tok);
+  if (!Tok.is(tok::eod)) {
+    ReleaseAssertionInfo(AI);
+    AI = 0;
+    return DiscardUntilEndOfDirective();
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // Preprocessor Conditional Directive Handling.
Index: clang/lib/Lex/PPExpressions.cpp
===================================================================
--- clang.orig/lib/Lex/PPExpressions.cpp	2011-11-30 11:39:35.000000000 +1000
+++ clang/lib/Lex/PPExpressions.cpp	2011-11-30 12:28:36.013697400 +1000
@@ -11,12 +11,9 @@
 // which parses and evaluates integer constant expressions for #if directives.
 //
 //===----------------------------------------------------------------------===//
-//
-// FIXME: implement testing for #assert's.
-//
-//===----------------------------------------------------------------------===//
 
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/AssertionInfo.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/CodeCompletionHandler.h"
@@ -381,7 +378,45 @@
     return false;
   }
 
-  // FIXME: Handle #assert
+  case tok::hash: {
+    Token PredicateTok;
+    PP.LexUnexpandedToken(PredicateTok);
+
+    AssertionInfo *AI = PP.AllocateAssertionInfo(PredicateTok.getLocation());
+    PP.LexUnexpandedToken(PeekTok);
+    if (PeekTok.isNot(tok::l_paren) || PredicateTok.getIdentifierInfo() == 0) {
+      PP.Diag(PredicateTok, diag::err_pp_expr_bad_token_start_expr);
+      PP.ReleaseAssertionInfo(AI);
+      AI = 0;
+      return true;
+    }
+
+    while (true) {
+      PP.LexUnexpandedToken(PeekTok);
+      if (PeekTok.is(tok::r_paren) || PeekTok.is(tok::eod)) {
+        break;
+      }
+      AI->AddToken(PeekTok);
+    }
+
+    // check for the closing ), if we don't have it relase the AssertionInfo
+    // and discard the rest of the directive
+    if (!PeekTok.is(tok::r_paren)) {
+      PP.Diag(PredicateTok, diag::err_pp_expr_bad_token_start_expr);
+      PP.ReleaseAssertionInfo(AI);
+      AI = 0;
+      return true;
+    }
+    PP.LexUnexpandedToken(PeekTok);
+
+    IdentifierInfo *II = PredicateTok.getIdentifierInfo();
+
+    Result.Val = PP.IsAsserted(II, AI) ? 1 : 0;
+    PP.ReleaseAssertionInfo(AI);
+    AI = 0;
+    return false;
+  }
+
   }
 }
 
Index: clang/include/clang/Lex/AssertionInfo.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/include/clang/Lex/AssertionInfo.h	2011-12-02 12:25:43.158898000 +1000
@@ -0,0 +1,57 @@
+//===--- AssertionInfo.h - C Language Family Preprocessor --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the AssertionInfo structure used to store information
+//  about GNU-style pre-processor assertions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASSERTIONINFO_H
+#define LLVM_CLANG_ASSERTIONINFO_H
+
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace clang {
+  class Preprocessor;
+
+  /// AssertionInfo - Each identifier that is used as a predicate in an
+  /// assertion statement has one or more instances of this class associated
+  /// with it to store the values pattern(s) asserted for it
+  class AssertionInfo {
+    /// AssertLoc - The SourceLocation of the assertion
+    SourceLocation AssertLoc;
+
+    /// ValueTokens - The tokens that make up the assertion
+    llvm::SmallVector<Token, 8> ValueTokens;
+
+    ~AssertionInfo() { }
+  public:
+    AssertionInfo(SourceLocation Loc) : AssertLoc(Loc) { }
+
+    void Destory() {
+      ValueTokens.clear();
+      this->~AssertionInfo();
+    }
+
+    /// AddToken - Adds a single token to the assertion's token sequence
+    void AddToken(Token &t) {
+      ValueTokens.push_back(t);
+    }
+
+    /// equals - returns true iff AI has the same tokens as this 
+    /// AssertionInfo instance
+    bool equals(AssertionInfo *AI, Preprocessor &PP);
+  };
+
+} // end namespace clang
+
+#endif
Index: clang/lib/Lex/AssertionInfo.cpp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/lib/Lex/AssertionInfo.cpp	2011-11-30 13:04:08.620004000 +1000
@@ -0,0 +1,57 @@
+//===-- AssertionInfo.cpp - AssertionInfo implementation ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the AssertionInfo class used to track
+// information about GNU-style pre-processor assertions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/AssertionInfo.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+bool AssertionInfo::equals(AssertionInfo *AI, Preprocessor &PP) {
+  if (ValueTokens.size() != AI->ValueTokens.size()) {
+    return false;
+  }
+
+  for (unsigned i = 0, e = ValueTokens.size(); i != e; ++i) {
+    const Token &A = ValueTokens[i];
+    const Token &B = AI->ValueTokens[i];
+
+    if (A.getKind() != B.getKind()) {
+      return false;
+    }
+
+    // If this isn't the first token, check that the whitespace and
+    // start-of-line characteristics match.
+    if (i != 0 &&
+        (A.isAtStartOfLine() != B.isAtStartOfLine() ||
+         A.hasLeadingSpace() != B.hasLeadingSpace())) {
+      return false;
+    }
+
+    // If the tokens to be compared are identifiers, the comparison is easy
+    if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
+      if (A.getIdentifierInfo() != B.getIdentifierInfo()) {
+        return false;
+      }
+      continue;
+    }
+
+    // Otherwise, check the token spelling
+    if (PP.getSpelling(A) != PP.getSpelling(B)) {
+      return false;
+    }
+  }
+
+  // The tokens all matched
+  return true;
+}
Index: clang/lib/Lex/PPAssertionHandler.cpp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/lib/Lex/PPAssertionHandler.cpp	2011-11-30 13:06:16.569251500 +1000
@@ -0,0 +1,73 @@
+//===-- PPAssertionHandler.cpp - handling of PP assert/unassert directives -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the pre-processor methods for handling GNU-style
+// pre-processor asserts and unasserts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LexDiagnostic.h"
+
+using namespace clang;
+
+void Preprocessor::AddAssertionValue(IdentifierInfo *II, AssertionInfo *AI) {
+  bool alreadyAsserted = false;
+  if (!AssertedValues[II].empty()) {
+    for (std::vector<AssertionInfo*>::iterator I = AssertedValues[II].begin(),
+                                               E = AssertedValues[II].end();
+         I != E; ++I) {
+      if ((*I)->equals(AI, *this)) {
+        alreadyAsserted = true;
+        break;
+      }
+    }
+  }
+
+  if (!alreadyAsserted) {
+    AssertedValues[II].push_back(AI);
+  }
+}
+
+bool Preprocessor::IsAsserted(IdentifierInfo *II, AssertionInfo *AI) {
+  if (AssertedValues.find(II) != assertion_end() && 
+      !AssertedValues[II].empty()) {
+    for (std::vector<AssertionInfo*>::iterator I = AssertedValues[II].begin(),
+                                               E = AssertedValues[II].end();
+         I != E; ++I) {
+      if ((*I)->equals(AI, *this)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+void Preprocessor::RemoveAssertionValue(IdentifierInfo *II, AssertionInfo *AI){
+  for (std::vector<AssertionInfo*>::iterator I = AssertedValues[II].begin(),
+                                             E = AssertedValues[II].end();
+       I != E; ++I) {
+    if ((*I)->equals(AI, *this)) {
+      AssertedValues[II].erase(I);
+      break;
+    }
+  }
+}
+
+void Preprocessor::RemoveAssertion(IdentifierInfo *II) {
+  // deallocate all of the asserted values for the predicate
+  for (std::vector<AssertionInfo*>::iterator I = AssertedValues[II].begin(),
+                                             E = AssertedValues[II].end();
+       I != E; ++I) {
+    ReleaseAssertionInfo(*I);
+  }
+
+  // remove the predicate from the assertion table
+  AssertedValues.erase(II);
+}
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang.orig/lib/Lex/Preprocessor.cpp	2011-11-30 11:39:46.000000000 +1000
+++ clang/lib/Lex/Preprocessor.cpp	2011-12-01 15:51:48.953885400 +1000
@@ -62,7 +62,7 @@
     CodeCompletionFile(0), CodeCompletionOffset(0), CodeCompletionReached(0),
     SkipMainFilePreamble(0, true), CurPPLexer(0), 
     CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0), MacroArgCache(0), 
-    Record(0), MIChainHead(0), MICache(0) 
+    Record(0), MIChainHead(0), MICache(0), AIChainHead(0), AICache(0)
 {
   OwnsHeaderSearch = OwnsHeaders;
   
@@ -267,6 +267,16 @@
   return Macros.end();
 }
 
+Preprocessor::assertion_iterator
+Preprocessor::assertion_begin() const {
+  return AssertedValues.begin();
+}
+
+Preprocessor::assertion_iterator
+Preprocessor::assertion_end() const {
+  return AssertedValues.end();
+}
+
 bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
                                           unsigned CompleteLine,
                                           unsigned CompleteColumn) {
Index: clang/test/Preprocessor/assertion.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/test/Preprocessor/assertion.c	2011-12-02 11:13:34.975288500 +1000
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -E %s | grep '^A$'
+// RUN: %clang_cc1 -E %s | grep '^NOT C$'
+// RUN: %clang_cc1 -E %s | grep '^NOT A2$'
+// RUN: %clang_cc1 -E %s | grep '^NO TEST$'
+// RUN: %clang_cc1 -E %s | grep '^OK$'
+
+#assert test(A)
+#assert test(B)
+
+#if #test(A)
+A
+#else
+NOT A
+#endif
+
+#if #test(C)
+C
+#else
+NOT C
+#endif
+
+#unassert test(A)
+#if #test(A)
+A2
+#else
+NOT A2
+#endif
+
+#unassert test
+#if #test(A) || #test(B)
+TEST
+#else
+NO TEST
+#endif
+
+#unassert val
+OK
Index: clang/test/Preprocessor/assertion_whitespace.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/test/Preprocessor/assertion_whitespace.c	2011-12-02 11:13:37.872156300 +1000
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -E %s | grep '^INTERNAL$'
+// RUN: %clang_cc1 -E %s | grep '^EXTERNAL1 IGNORED$'
+// RUN: %clang_cc1 -E %s | grep '^EXTERNAL2 IGNORED$'
+
+#assert test(x + y)
+
+#if #test(x+y)
+INTERNAL IGNORED
+#else
+INTERNAL
+#endif
+
+#if #test( x + y)
+EXTERNAL1 IGNORED
+#else
+EXTERNAL1
+#endif
+
+#if #test(x + y )
+EXTERNAL2 IGNORED
+#else
+EXTERNAL2
+#endif
