Index: clang/include/clang/Lex/AssertionInfo.h
===================================================================
--- clang.orig/include/clang/Lex/AssertionInfo.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Lex/AssertionInfo.h	2011-12-14 10:56:08.859889000 +1000
@@ -33,9 +33,12 @@
     /// ValueTokens - The tokens that make up the assertion
     llvm::SmallVector<Token, 8> ValueTokens;
 
+    /// IsFromAST - True if this assertion was loaded from an AST file.
+    bool IsFromAST : 1;
+
     ~AssertionInfo() { }
   public:
-    AssertionInfo(SourceLocation Loc) : AssertLoc(Loc) { }
+    AssertionInfo(SourceLocation Loc) : AssertLoc(Loc), IsFromAST(false) { }
 
     void destroy() {
       ValueTokens.clear();
@@ -55,9 +58,31 @@
         AssertLoc;
     }
 
+    /// isFromAST - Return true if this assertion was loaded from an AST
+    bool isFromAST() const { return IsFromAST; }
+
+    /// setIsFromAST - Set whether this assertion was loaded from an AST file.
+    void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
+    /// getNumTokens - return the number of tokens in the assertion value
+    unsigned getNumTokens() const {
+      return ValueTokens.size();
+    }
+
+    /// getValueToken - return the specified token from the value token
+    /// sequence for this assertion.
+    const Token &getValueToken(unsigned Tok) const {
+      assert(Tok < ValueTokens.size() && "Invalid token #");
+      return ValueTokens[Tok];
+    }
+
     /// equals - returns true iff AI has the same tokens as this
     /// AssertionInfo instance
     bool equals(AssertionInfo *AI, Preprocessor &PP) const;
+
+    typedef llvm::SmallVector<Token, 8>::const_iterator value_iterator;
+    value_iterator value_begin() const { return ValueTokens.begin(); }
+    value_iterator value_end() const { return ValueTokens.end(); }
   };
 
 } // end namespace clang
Index: clang/include/clang/Lex/PPCallbacks.h
===================================================================
--- clang.orig/include/clang/Lex/PPCallbacks.h	2011-12-13 14:06:38.000000000 +1000
+++ clang/include/clang/Lex/PPCallbacks.h	2011-12-13 14:07:26.537317500 +1000
@@ -25,6 +25,7 @@
   class Token;
   class IdentifierInfo;
   class MacroInfo;
+  class AssertionInfo;
 
 /// PPCallbacks - This interface provides a way to observe the actions of the
 /// preprocessor as it does its thing.  Clients can define their hooks here to
@@ -178,6 +179,17 @@
   /// MI is released immediately following this callback.
   virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
   }
+
+  /// assertAdded - This hook is called when an assert directive is seen.
+  virtual void assertAdded(const Token &AssertPredicate,
+                           const AssertionInfo *AI) {
+  }
+
+  /// assertRemoved - This hook is called when an unassert directive for a key
+  /// value pair is seen.
+  virtual void assertRemoved(const Token &AssertPredicate,
+                             const AssertionInfo *AI) {
+  }
   
   /// Defined - This hook is called whenever the 'defined' operator is seen.
   virtual void Defined(const Token &MacroNameTok) {
Index: clang/include/clang/Lex/PreprocessingRecord.h
===================================================================
--- clang.orig/include/clang/Lex/PreprocessingRecord.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Lex/PreprocessingRecord.h	2011-12-15 06:06:13.416871600 +1000
@@ -61,10 +61,13 @@
       /// #import, or \c #include_next.
       InclusionDirectiveKind,
 
+      /// \brief A GCC-stle pre-processor assertion \c #assert
+      AssertionKind,
+
       /// @}
 
       FirstPreprocessingDirective = MacroDefinitionKind,
-      LastPreprocessingDirective = InclusionDirectiveKind
+      LastPreprocessingDirective = AssertionKind
     };
 
   private:
@@ -253,6 +256,31 @@
     }
     static bool classof(const InclusionDirective *) { return true; }
   };
+
+  /// \brief Record of the locaiton of an assert directive of the form
+  /// key(value) following an \c #assert or \c #unassert directive.
+  class AssertDefinition : public PreprocessingDirective {
+    /// \brief the name of the predicate for which the value is being asserted
+    const IdentifierInfo *Name;
+
+  public:
+    explicit AssertDefinition(const IdentifierInfo *Name, SourceRange Range)
+      : PreprocessingDirective(AssertionKind, Range), Name(Name) { }
+
+    /// \brief Retrieve the name of the predicate for which the value
+    /// was asserted
+    const IdentifierInfo *getName() const { return Name; }
+
+    /// \brief Retrieve the location of the assertion
+    SourceLocation getLocation() const { return getSourceRange().getBegin(); }
+
+    // implement isa/cast/dyncast/etc
+    static bool classof(const PreprocessedEntity *PE) {
+      return PE->getKind() == AssertionKind;
+    }
+
+    static bool classof(const AssertDefinition *) { return true; }
+  };
   
   /// \brief An abstract class that should be subclassed by any external source
   /// of preprocessing record entries.
@@ -320,6 +348,11 @@
     /// \brief Mapping from MacroInfo structures to their definitions.
     llvm::DenseMap<const MacroInfo *, PPEntityID> MacroDefinitions;
 
+    /// \brief Mapping from AssertionInfo structures to their definitions.
+    llvm::DenseMap<const IdentifierInfo *,
+      SmallVector<std::pair<const AssertionInfo *, PPEntityID>, 1> >
+      AssertDefinitions;
+
     /// \brief External source of preprocessed entities.
     ExternalPreprocessingRecordSource *ExternalSource;
 
@@ -351,6 +384,9 @@
     /// \brief Register a new macro definition.
     void RegisterMacroDefinition(MacroInfo *Macro, PPEntityID PPID);
     
+    /// \breif Register a new assert definition.
+    void registerAssertDefinition(IdentifierInfo *II, AssertionInfo *Assert,
+                                  PPEntityID PPID);
   public:
     /// \brief Construct a new preprocessing record.
     PreprocessingRecord(SourceManager &SM, bool IncludeNestedMacroExpansions);
@@ -547,6 +583,13 @@
                                     StringRef SearchPath,
                                     StringRef RelativePath);
 
+    AssertDefinition *findAssertDefinition(const IdentifierInfo *II,
+                                           const AssertionInfo *AI);
+
+    virtual void assertAdded(const Token &Predicate, const AssertionInfo *AI);
+    virtual void assertRemoved(const Token &Predicate,
+                               const AssertionInfo *AI);
+
   private:
     /// \brief Cached result of the last \see getPreprocessedEntitiesInRange
     /// query.
Index: clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- clang.orig/lib/Frontend/ASTUnit.cpp	2011-11-25 13:34:32.000000000 +1000
+++ clang/lib/Frontend/ASTUnit.cpp	2011-12-15 06:04:53.666310200 +1000
@@ -802,6 +802,11 @@
   virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
     Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash);
   }
+
+  virtual void assertAdded(const Token &AssertPredicateTok,
+                           const AssertionInfo *AI) {
+    Hash = llvm::HashString(AssertPredicateTok.getIdentifierInfo()->getName(), Hash);
+  }
 };
 
 /// \brief Add the given declaration to the hash of all top-level entities.
Index: clang/lib/Frontend/PrintPreprocessedOutput.cpp
===================================================================
--- clang.orig/lib/Frontend/PrintPreprocessedOutput.cpp	2011-11-25 13:34:33.000000000 +1000
+++ clang/lib/Frontend/PrintPreprocessedOutput.cpp	2011-12-15 06:04:35.839290500 +1000
@@ -16,6 +16,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "clang/Lex/AssertionInfo.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/PPCallbacks.h"
 #include "clang/Lex/Pragma.h"
@@ -73,6 +74,26 @@
   }
 }
 
+static void PrintAssertion(const IdentifierInfo &II, const AssertionInfo &AI,
+                           Preprocessor &PP, raw_ostream &OS) {
+  OS << II.getName();
+
+  OS << '(';
+
+  llvm::SmallString<128> SpellingBuffer;
+  for (AssertionInfo::value_iterator S = AI.value_begin(), I = AI.value_begin(),
+       E = AI.value_end(); I != E; ++I) {
+    // leading spaces around the value token sequence is ignored so standardize to no
+    // space for ease of reading and compactness of formatting
+    if (I != S && I->hasLeadingSpace())
+      OS << ' ';
+
+    OS << PP.getSpelling(*I, SpellingBuffer);
+  }
+
+  OS << ')';
+}
+
 //===----------------------------------------------------------------------===//
 // Preprocessed token printer
 //===----------------------------------------------------------------------===//
@@ -153,6 +174,12 @@
 
   /// MacroUndefined - This hook is called whenever a macro #undef is seen.
   void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI);
+
+  /// assertAdded - This hook is called whenever a #assert is seen.
+  void assertAdded(const Token &AssertPredicateTok, const AssertionInfo *AI);
+
+  /// assertRemoved - This hook is called whenever a #unassert is seen.
+  void assertRemoved(const Token &AssertPredicateTok, const AssertionInfo *AI);
 };
 }  // end anonymous namespace
 
@@ -321,6 +348,28 @@
   EmittedMacroOnThisLine = true;
 }
 
+void PrintPPOutputPPCallbacks::assertAdded(const Token &AssertPredicateTok,
+                                           const AssertionInfo *AI) {
+  // Only print out asserts in -dD mode.
+  if (!DumpDefines)
+    return;
+  MoveToLine(AI->getAssertionLoc());
+  OS << "#assert ";
+  PrintAssertion(*AssertPredicateTok.getIdentifierInfo(), *AI, PP, OS);
+  EmittedMacroOnThisLine = true;
+}
+
+void PrintPPOutputPPCallbacks::assertRemoved(const Token &AssertPredicateTok,
+                                             const AssertionInfo *AI) {
+  // Only print out unasserts in -dD mode.
+  if (!DumpDefines)
+    return;
+  MoveToLine(AI->getAssertionLoc());
+  OS << "#unassert ";
+  PrintAssertion(*AssertPredicateTok.getIdentifierInfo(), *AI, PP, OS);
+  EmittedMacroOnThisLine = true;
+}
+
 void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
                                              const IdentifierInfo *Kind,
                                              const std::string &Str) {
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang.orig/lib/Lex/PPDirectives.cpp	2011-12-15 11:03:25.413519000 +1000
+++ clang/lib/Lex/PPDirectives.cpp	2011-12-15 09:11:56.038076200 +1000
@@ -1852,6 +1852,11 @@
   // add to AI
   if (AI) {
     addAssertionValue(AssertionPredicateTok.getIdentifierInfo(), AI);
+
+    // If the callbacks want to know, tell them about the #assert
+    if (Callbacks) {
+      Callbacks->assertAdded(AssertionPredicateTok, AI);
+    }
   }
 
   // check there is nothing after the closing ), if we have anything release
@@ -1878,12 +1883,26 @@
   LexUnexpandedToken(Tok);
 
   if (Tok.is(tok::eod)) {
+    // If the callbacks want to know, tell them about the #unassert
+    if (Callbacks) {
+      for (assertion_value_iterator I = AssertedValues[II].begin(),
+                                    E = AssertedValues[II].end();
+           I != E; ++I) {
+        Callbacks->assertRemoved(AssertionPredicateTok, *I);
+      }
+    }
+
     removeAssertion(II);
   } else {
     AssertionInfo *AI = readAssertionValue(Tok,
                                           AssertionPredicateTok.getLocation());
 
     if (AI) {
+      // If the callbacks want to know, tell them about the #unassert
+      if (Callbacks) {
+        Callbacks->assertRemoved(AssertionPredicateTok, AI);
+      }
+
       removeAssertionValue(II, AI);
       releaseAssertionInfo(AI);
     }
Index: clang/lib/Lex/PreprocessingRecord.cpp
===================================================================
--- clang.orig/lib/Lex/PreprocessingRecord.cpp	2011-12-13 13:48:57.000000000 +1000
+++ clang/lib/Lex/PreprocessingRecord.cpp	2011-12-15 06:05:16.371608800 +1000
@@ -12,6 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/AssertionInfo.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Token.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -289,6 +290,11 @@
   MacroDefinitions[Macro] = PPID;
 }
 
+void PreprocessingRecord::registerAssertDefinition(IdentifierInfo *II,
+                                          AssertionInfo *AI, PPEntityID PPID) {
+  AssertDefinitions[II].push_back(std::make_pair(AI, PPID));
+}
+
 /// \brief Retrieve the preprocessed entity at the given ID.
 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
   if (PPID < 0) {
@@ -399,9 +405,60 @@
   addPreprocessedEntity(ID);
 }
 
+AssertDefinition *PreprocessingRecord::findAssertDefinition(
+                           const IdentifierInfo *II, const AssertionInfo *AI) {
+  if (AssertDefinitions.find(II) == AssertDefinitions.end())
+    return 0;
+
+  for (SmallVector<std::pair<const AssertionInfo*, PPEntityID>, 1>::iterator
+       I = AssertDefinitions[II].begin(), E = AssertDefinitions[II].end();
+       I != E; ++I) {
+    if (I->first == AI) {
+      PreprocessedEntity *Entity = getPreprocessedEntity(I->second);
+      if (Entity->isInvalid())
+        return 0;
+      return cast<AssertDefinition>(Entity);
+    }
+  }
+
+  return 0;
+}
+
+void PreprocessingRecord::assertAdded(const Token &Predicate,
+                                      const AssertionInfo *AI) {
+  SourceRange R(AI->getAssertionLoc(), AI->getAssertionEndLoc());
+  IdentifierInfo *II = Predicate.getIdentifierInfo();
+  AssertDefinition *Def = new (*this) AssertDefinition(II, R);
+  addPreprocessedEntity(Def);
+  AssertDefinitions[II].push_back(std::pair<const AssertionInfo *, PPEntityID>(
+    AI, getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/ false)));
+}
+
+void PreprocessingRecord::assertRemoved(const Token &Predicate,
+                                        const AssertionInfo *AI) {
+  IdentifierInfo *II = Predicate.getIdentifierInfo();
+  llvm::DenseMap<const IdentifierInfo *, SmallVector<
+      std::pair<const AssertionInfo *, PPEntityID>, 1> >::iterator Pos =
+      AssertDefinitions.find(II);
+  if (Pos == AssertDefinitions.end())
+    return;
+
+  for (SmallVector<std::pair<const AssertionInfo*, PPEntityID>, 1>::iterator
+       I = Pos->second.begin(), E = Pos->second.end();
+       I != E; ++I) {
+    if (I->first == AI) {
+      Pos->second.erase(I);
+      break;
+    }
+  }
+  if (Pos->second.size() == 0)
+    AssertDefinitions.erase(Pos);
+}
+
 size_t PreprocessingRecord::getTotalMemory() const {
   return BumpAlloc.getTotalMemory()
     + llvm::capacity_in_bytes(MacroDefinitions)
+    + llvm::capacity_in_bytes(AssertDefinitions)
     + llvm::capacity_in_bytes(PreprocessedEntities)
     + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
 }
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang.orig/include/clang/Serialization/ASTBitCodes.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Serialization/ASTBitCodes.h	2011-12-13 16:53:35.235766600 +1000
@@ -464,6 +464,8 @@
     enum PreprocessorRecordTypes {
       // The macros in the PP section are a PP_MACRO_* instance followed by a
       // list of PP_TOKEN instances for each token in the definition.
+      // Asserts are PP_ASSERT followed by a list of of PP_TOKEN instances for
+      // each token in the asserted value.
 
       /// \brief An object-like macro definition.
       /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
@@ -476,7 +478,11 @@
 
       /// \brief Describes one token.
       /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
-      PP_TOKEN = 3
+      PP_TOKEN = 3,
+
+      /// \brief Describes an assertion
+      /// [PP_ASSERT, IdentInfoID, SLoc]
+      PP_ASSERT = 4
     };
 
     /// \brief Record types used within a preprocessor detail block.
@@ -489,7 +495,11 @@
       
       /// \brief Describes an inclusion directive within the preprocessing
       /// record.
-      PPD_INCLUSION_DIRECTIVE = 2
+      PPD_INCLUSION_DIRECTIVE = 2,
+
+      /// \brief Describes an assert directive within the preprocessing
+      /// record.
+      PPD_ASSERT = 3
     };
     
     /// \defgroup ASTAST AST file AST constants
Index: clang/include/clang/Serialization/ASTDeserializationListener.h
===================================================================
--- clang.orig/include/clang/Serialization/ASTDeserializationListener.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Serialization/ASTDeserializationListener.h	2011-12-13 16:51:40.955922900 +1000
@@ -23,6 +23,7 @@
 class ASTReader;
 class QualType;
 class MacroDefinition;
+class AssertDefinition;
   
 class ASTDeserializationListener {
 protected:
@@ -47,6 +48,9 @@
   /// \brief A macro definition was read from the AST file.
   virtual void MacroDefinitionRead(serialization::PreprocessedEntityID, 
                                    MacroDefinition *MD) { }
+  /// \brief An assetion was read from the AST file.
+  virtual void assertionRead(serialization::PreprocessedEntityID,
+                             AssertDefinition *AD) { }
 };
 
 }
Index: clang/lib/Frontend/FrontendAction.cpp
===================================================================
--- clang.orig/lib/Frontend/FrontendAction.cpp	2011-12-13 13:48:57.000000000 +1000
+++ clang/lib/Frontend/FrontendAction.cpp	2011-12-13 16:49:25.841227500 +1000
@@ -64,6 +64,11 @@
     if (Previous)
       Previous->MacroDefinitionRead(PPID, MD);
   }
+  virtual void assertionRead(serialization::PreprocessedEntityID PPID,
+                             AssertDefinition *AD) {
+    if (Previous)
+      Previous->assertionRead(PPID, AD);
+  }
 };
 
 /// \brief Dumps deserialized declarations.
Index: clang/lib/Frontend/MultiplexConsumer.cpp
===================================================================
--- clang.orig/lib/Frontend/MultiplexConsumer.cpp	2011-12-13 13:48:57.000000000 +1000
+++ clang/lib/Frontend/MultiplexConsumer.cpp	2011-12-13 16:53:31.522960000 +1000
@@ -39,6 +39,8 @@
   virtual void SelectorRead(serialization::SelectorID iD, Selector Sel);
   virtual void MacroDefinitionRead(serialization::PreprocessedEntityID, 
                                    MacroDefinition *MD);
+  virtual void assertionRead(serialization::PreprocessedEntityID,
+                             AssertDefinition *AD);
 private:
   std::vector<ASTDeserializationListener*> Listeners;
 };
@@ -84,6 +86,12 @@
     Listeners[i]->MacroDefinitionRead(ID, MD);
 }
 
+void MultiplexASTDeserializationListener::assertionRead(
+    serialization::PreprocessedEntityID ID, AssertDefinition *AD) {
+  for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+    Listeners[i]->assertionRead(ID, AD);
+}
+
 // This ASTMutationListener forwards its notifications to a set of
 // child listeners.
 class MultiplexASTMutationListener : public ASTMutationListener {
Index: clang/include/clang/Basic/IdentifierTable.h
===================================================================
--- clang.orig/include/clang/Basic/IdentifierTable.h	2011-11-25 13:34:09.000000000 +1000
+++ clang/include/clang/Basic/IdentifierTable.h	2011-12-15 10:55:23.839866900 +1000
@@ -69,7 +69,9 @@
   bool OutOfDate              : 1; // True if there may be additional
                                    // information about this identifier
                                    // stored externally.
-  // 2 bits left in 32-bit word.
+  bool HasAssertedVals        : 1; // True if there are any values asserted
+                                   // for this identifier using #assert.
+  // 1 bit left in 32-bit word.
   
   void *FETokenInfo;               // Managed by the language front-end.
   llvm::StringMapEntry<IdentifierInfo*> *Entry;
@@ -138,6 +140,15 @@
       RecomputeNeedsHandleIdentifier();
   }
 
+  /// hasAssertedValues - Return true if this identifier is the predicate in
+  /// a preprocessor #assert which is currently alive.
+  bool hasAssertedValues() const {
+    return HasAssertedVals;
+  }
+  void setHasAssertedValues(bool Val) {
+    HasAssertedVals = Val;
+  }
+
   /// getTokenID - If this is a source-language token (e.g. 'for'), this API
   /// can be used to cause the lexer to map identifiers to source-language
   /// tokens.
Index: clang/include/clang/Lex/ExternalPreprocessorSource.h
===================================================================
--- clang.orig/include/clang/Lex/ExternalPreprocessorSource.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Lex/ExternalPreprocessorSource.h	2011-12-14 11:35:52.562962800 +1000
@@ -33,6 +33,12 @@
   
   /// \brief Update an out-of-date identifier.
   virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
+
+  /// \brief Read the assertions made in this external preproessor source.
+  virtual void readAssertions() = 0;
+
+  /// \brief Read the values asserted for the given predicate.
+  virtual void loadAssertedValues(IdentifierInfo *II) = 0;
 };
   
 }
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang.orig/include/clang/Lex/Preprocessor.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Lex/Preprocessor.h	2011-12-14 23:43:47.926938000 +1000
@@ -123,6 +123,9 @@
   /// \brief Whether we have already loaded macros from the external source.
   mutable bool ReadMacrosFromExternalSource : 1;
 
+  /// \brief Whether we have already loaded the assertions from the external source.
+  mutable bool readAssertsFromExternalSource : 1;
+
   /// Identifiers - This is mapping/lookup information for all identifiers in
   /// the program, including program keywords.
   mutable IdentifierTable Identifiers;
@@ -486,15 +489,27 @@
   /// walk the current state of the assertions table. This visits every
   /// currently asserted predicate
   typedef llvm::DenseMap<IdentifierInfo*,
-      UsuallyTinyPtrVector<AssertionInfo> >::iterator assertion_iterator;
-  assertion_iterator assertion_begin();
-  assertion_iterator assertion_end();
+      UsuallyTinyPtrVector<AssertionInfo> >::const_iterator assertion_iterator;
+  assertion_iterator assertion_begin(bool IncludeExternalAsserts = true) const;
+  assertion_iterator assertion_end(bool IncludeExternalAsserts = true) const;
 
   /// assertion_value_iterator - A helpful type for traversing the values
   /// asserted for a given predicate
   typedef UsuallyTinyPtrVector<AssertionInfo>::iterator
                                                       assertion_value_iterator;
 
+  assertion_value_iterator getAssertionsBegin(IdentifierInfo *II) const {
+    assert(AssertedValues.find(II) != AssertedValues.end() &&
+           "Identifier has no known assertions!");
+    return AssertedValues.find(II)->second.begin();
+  }
+
+  assertion_value_iterator getAssertionsEnd(IdentifierInfo *II) const {
+    assert(AssertedValues.find(II) != AssertedValues.end() &&
+           "Identifier has no known assertions!");
+    return AssertedValues.find(II)->second.end();
+  }
+
   const std::string &getPredefines() const { return Predefines; }
   /// setPredefines - Set the predefines for this Preprocessor.  These
   /// predefines are automatically injected when parsing the main file.
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang.orig/include/clang/Serialization/ASTReader.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Serialization/ASTReader.h	2011-12-14 15:29:55.726623100 +1000
@@ -65,6 +65,7 @@
 class CXXCtorInitializer;
 class GotoStmt;
 class MacroDefinition;
+class AssertDefinition;
 class NamedDecl;
 class OpaqueValueExpr;
 class Preprocessor;
@@ -389,6 +390,12 @@
   /// record resides.
   llvm::DenseMap<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets;
 
+  typedef SmallVector<uint64_t, 1> AssertOffsetList;
+  /// \brief mapping from identifiers that appear as assertion predicates
+  /// whose definitions have not yet been deserialized to the global offset
+  /// where the assert record resides.
+  llvm::DenseMap<IdentifierInfo *, AssertOffsetList> UnreadAssertOffsets;
+
   typedef ContinuousRangeMap<unsigned, Module *, 4>
     GlobalPreprocessedEntityMapType;
 
@@ -570,6 +577,12 @@
   /// \brief The total number of macros stored in the chain.
   unsigned TotalNumMacros;
 
+  /// \brief the number asserts de-serialized from the chain.
+  unsigned NumAssertsRead;
+
+  /// \brief The total number asserts stored in the chain.
+  unsigned TotalNumAsserts;
+
   /// \brief The number of selectors that have been read.
   unsigned NumSelectorsRead;
 
@@ -738,6 +751,9 @@
 
   void PassInterestingDeclsToConsumer();
 
+  void readPreprocessor();
+  bool PreprocessorRun;
+
   /// \brief Produce an error diagnostic and return true.
   ///
   /// This routine should only be used for fatal errors that have to
@@ -1277,6 +1293,9 @@
   /// \brief Reads the macro record located at the given offset.
   void ReadMacroRecord(Module &F, uint64_t Offset);
 
+  /// \brief Read the assert located at the given offset.
+  void readAssertRecord(Module &F, uint64_t Offset);
+
   /// \brief Determine the global preprocessed entity ID that corresponds to
   /// the given local ID within the given module.
   serialization::PreprocessedEntityID
@@ -1301,6 +1320,15 @@
   void LoadMacroDefinition(
                      llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos);
 
+  void setIdentifierIsAssert(IdentifierInfo *II, Module &F, uint64_t Offset);
+
+  virtual void readAssertions();
+
+  virtual void loadAssertedValues(
+             llvm::DenseMap<IdentifierInfo *, AssertOffsetList>::iterator Pos);
+
+  virtual void loadAssertedValues(IdentifierInfo *II);
+
   /// \brief Retrieve the AST context that this AST reader supplements.
   ASTContext &getContext() { return Context; }
 
Index: clang/include/clang/Serialization/ASTWriter.h
===================================================================
--- clang.orig/include/clang/Serialization/ASTWriter.h	2011-12-13 13:48:57.000000000 +1000
+++ clang/include/clang/Serialization/ASTWriter.h	2011-12-14 12:49:10.388268400 +1000
@@ -46,6 +46,7 @@
 class HeaderSearch;
 class IdentifierResolver;
 class MacroDefinition;
+class AssertDefinition;
 class MemorizeStatCalls;
 class OpaqueValueExpr;
 class OpenCLOptions;
@@ -72,6 +73,7 @@
 public:
   typedef SmallVector<uint64_t, 64> RecordData;
   typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+  typedef SmallVector<uint64_t, 1> AssertOffsetList;
 
   friend class ASTDeclWriter;
 private:
@@ -224,14 +226,28 @@
   /// defined.
   llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets;
 
+  /// \brief Offsets of each of the assertion defintions in the bitstream
+  /// For each idnetifier that has been asserted, this map provides the
+  /// offsets to the predicate defintions in the bitstream.
+  llvm::DenseMap<const IdentifierInfo *, AssertOffsetList>
+      AssertOffsets;
+
   /// \brief The set of identifiers that had macro definitions at some point.
   std::vector<const IdentifierInfo *> DeserializedMacroNames;
 
+  /// \brief The set of identifiers that had values asserted at some point.
+  std::vector<const IdentifierInfo *> DeserializedAssertPredicates;
+
   /// \brief Mapping from macro definitions (as they occur in the preprocessing
   /// record) to the macro IDs.
   llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID>
       MacroDefinitions;
 
+  /// \brief Mapping from assertion definitions (as they occur in the
+  /// preprocessing record) to the assert IDs.
+  llvm::DenseMap<const AssertDefinition *, serialization::PreprocessedEntityID>
+      AssertDefinitions;
+
   typedef SmallVector<uint64_t, 2> UpdateRecord;
   typedef llvm::DenseMap<const Decl *, UpdateRecord> DeclUpdateMap;
   /// \brief Mapping from declarations that came from a chained PCH to the
@@ -320,6 +336,9 @@
   /// \brief The number of macros written to the AST file.
   unsigned NumMacros;
 
+  /// \brief The number of asserted values written to the AST file.
+  unsigned NumAsserts;
+
   /// \brief The number of lexical declcontexts written to the AST
   /// file.
   unsigned NumLexicalDeclContexts;
@@ -482,6 +501,25 @@
     return MacroOffsets[II];
   }
 
+  /// \brief Retrieve the number of values asserted for the given identifier
+  ///
+  ///  The identifier must have at least one asserted value.
+  uint64_t getNumAssertValues(const IdentifierInfo *II) {
+    assert(AssertOffsets.find(II) != AssertOffsets.end() &&
+           "Identifier has no known asserted values");
+    return AssertOffsets[II].size();
+  }
+
+  /// \brief Retrieve a  pointer to the list of asserted vlaues for the
+  /// given identifier.
+  ///
+  /// The identifier must have at least one asserted value.
+  const AssertOffsetList *getAssertOffsets(const IdentifierInfo *II) {
+    assert(AssertOffsets.find(II) != AssertOffsets.end() &&
+           "Identifier has no known asserted values");
+    return &AssertOffsets[II];
+  }
+
   /// \brief Emit a reference to a type.
   void AddTypeRef(QualType T, RecordDataImpl &Record);
 
@@ -647,6 +685,8 @@
   void SelectorRead(serialization::SelectorID ID, Selector Sel);
   void MacroDefinitionRead(serialization::PreprocessedEntityID ID,
                            MacroDefinition *MD);
+  void assertionRead(serialization::PreprocessedEntityID ID,
+                     AssertDefinition *AD);
 
   // ASTMutationListener implementation.
   virtual void CompletedTagDefinition(const TagDecl *D);
Index: clang/lib/Basic/IdentifierTable.cpp
===================================================================
--- clang.orig/lib/Basic/IdentifierTable.cpp	2011-11-25 13:34:33.000000000 +1000
+++ clang/lib/Basic/IdentifierTable.cpp	2011-12-14 17:26:15.604951800 +1000
@@ -31,6 +31,7 @@
   TokenID = tok::identifier;
   ObjCOrBuiltinID = 0;
   HasMacro = false;
+  HasAssertedVals = false;
   IsExtension = false;
   IsCXX11CompatKeyword = false;
   IsPoisoned = false;
Index: clang/lib/Lex/PPAssertionHandler.cpp
===================================================================
--- clang.orig/lib/Lex/PPAssertionHandler.cpp	2011-12-14 10:25:43.000000000 +1000
+++ clang/lib/Lex/PPAssertionHandler.cpp	2011-12-15 11:40:20.284771900 +1000
@@ -13,12 +13,22 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
 #include "clang/Lex/LexDiagnostic.h"
 
 using namespace clang;
 
 void Preprocessor::addAssertionValue(IdentifierInfo *II, AssertionInfo *AI) {
   bool alreadyAsserted = false;
+
+  // if the identifier already says it has at least one asserted value, but we
+  // don't have any asserted values, then we need to inflate this identifier.
+  if (II->hasAssertedValues() && !AI->isFromAST() &&
+      AssertedValues.find(II) == AssertedValues.end()) {
+    getExternalSource()->loadAssertedValues(II);
+  }
+
+  // now check to see if the assertion already exists
   if (!AssertedValues[II].empty()) {
     for (assertion_value_iterator I = AssertedValues[II].begin(),
                                   E = AssertedValues[II].end();
@@ -30,12 +40,24 @@
     }
   }
 
+  // the assert is a nop if the assertion already exists
   if (!alreadyAsserted) {
     AssertedValues[II].push_back(AI);
+    II->setHasAssertedValues(true);
+    if (II->isFromAST() && !AI->isFromAST())
+      II->setChangedSinceDeserialization();
   }
 }
 
 bool Preprocessor::isAsserted(IdentifierInfo *II, AssertionInfo *AI) {
+  // if the identifier already says it has at least one asserted value, but we
+  // don't have any asserted values, then we need to inflate this identifier.
+  if (II->hasAssertedValues() &&
+      AssertedValues.find(II) == AssertedValues.end()) {
+      getExternalSource()->loadAssertedValues(II);
+  }
+
+  // run the search
   if (AssertedValues.find(II) != assertion_end() &&
       !AssertedValues[II].empty()) {
     for (assertion_value_iterator I = AssertedValues[II].begin(),
@@ -50,6 +72,13 @@
 }
 
 void Preprocessor::removeAssertionValue(IdentifierInfo *II, AssertionInfo *AI){
+  // if the identifier already says it has at least one asserted value, but we
+  // don't have any asserted values, then we need to inflate this identifier.
+  if (II->hasAssertedValues() &&
+      AssertedValues.find(II) == AssertedValues.end()) {
+    getExternalSource()->loadAssertedValues(II);
+  }
+
   // check if the assertion predicate is in the assertion table
   assertion_iterator iter = AssertedValues.find(II);
 
@@ -66,12 +95,26 @@
       AssertionInfo *toRelease = const_cast<AssertionInfo*>(*I);
       AssertedValues[II].erase(I);
       releaseAssertionInfo(toRelease);
+      if (II->isFromAST())
+        II->setChangedSinceDeserialization();
       break;
     }
   }
+
+  if (AssertedValues[II].empty()) {
+    AssertedValues.erase(II);
+    II->setHasAssertedValues(false);
+  }
 }
 
 void Preprocessor::removeAssertion(IdentifierInfo *II) {
+  // if the identifier already says it has at least one asserted value, but we
+  // don't have any asserted values, then we need to inflate this identifier.
+  if (II->hasAssertedValues() &&
+      AssertedValues.find(II) == AssertedValues.end()) {
+    getExternalSource()->loadAssertedValues(II);
+  }
+
   // check if the assertion predicate is in the assertion table
   assertion_iterator iter = AssertedValues.find(II);
 
@@ -90,4 +133,7 @@
 
   // remove the predicate from the assertion table
   AssertedValues.erase(II);
+  II->setHasAssertedValues(false);
+  if (II->isFromAST())
+    II->setChangedSinceDeserialization();
 }
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang.orig/lib/Lex/Preprocessor.cpp	2011-12-13 13:48:57.000000000 +1000
+++ clang/lib/Lex/Preprocessor.cpp	2011-12-14 11:42:24.402665500 +1000
@@ -145,6 +145,7 @@
   
   // We haven't read anything from the external source.
   ReadMacrosFromExternalSource = false;
+  readAssertsFromExternalSource = false;
   
   // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
   // This gets unpoisoned where it is allowed.
@@ -273,12 +274,22 @@
 }
 
 Preprocessor::assertion_iterator
-Preprocessor::assertion_begin() {
+Preprocessor::assertion_begin(bool IncludeExternalAsserts) const {
+  if (IncludeExternalAsserts && ExternalSource &&
+      !readAssertsFromExternalSource) {
+    readAssertsFromExternalSource = true;
+    ExternalSource->readAssertions();
+  }
   return AssertedValues.begin();
 }
 
 Preprocessor::assertion_iterator
-Preprocessor::assertion_end() {
+Preprocessor::assertion_end(bool IncludeExternalAsserts) const {
+  if (IncludeExternalAsserts && ExternalSource &&
+      !readAssertsFromExternalSource) {
+    readAssertsFromExternalSource = true;
+    ExternalSource->readAssertions();
+  }
   return AssertedValues.end();
 }
 
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang.orig/lib/Serialization/ASTReader.cpp	2011-12-13 13:48:57.000000000 +1000
+++ clang/lib/Serialization/ASTReader.cpp	2011-12-15 11:55:38.933925500 +1000
@@ -28,6 +28,7 @@
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLocVisitor.h"
+#include "clang/Lex/AssertionInfo.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Lex/Preprocessor.h"
@@ -518,7 +519,9 @@
     return II;
   }
 
-  unsigned Bits = ReadUnalignedLE16(d);
+  unsigned Bits = ReadUnalignedLE32(d);
+  bool HasAssertedValues = Bits & 0x01;
+  Bits >>= 1;
   bool CPlusPlusOperatorKeyword = Bits & 0x01;
   Bits >>= 1;
   bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
@@ -533,7 +536,7 @@
   Bits >>= 10;
 
   assert(Bits == 0 && "Extra bits in the identifier?");
-  DataLen -= 6;
+  DataLen -= 8;
 
   // Build the IdentifierInfo itself and link the identifier ID with
   // the new IdentifierInfo.
@@ -565,6 +568,18 @@
     Reader.SetIdentifierIsMacro(II, F, Offset);
     DataLen -= 4;
   }
+  // If this identifier has asserted values, deserialzie the assert
+  // definitions.
+  if (HasAssertedValues) {
+    II->setHasAssertedValues(true);
+    uint16_t NumAsserts = ReadUnalignedLE16(d);
+    DataLen -= 2;
+    for (unsigned i = 0; i < NumAsserts; ++i) {
+      uint32_t Offset = ReadUnalignedLE32(d);
+      Reader.setIdentifierIsAssert(II, F, Offset);
+      DataLen -= 4;
+    }
+  }
 
   Reader.SetIdentifierInfo(ID, II);
 
@@ -1378,6 +1393,115 @@
       Macro->AddTokenToBody(Tok);
       break;
     }
+
+    case PP_ASSERT: {
+      if (Macro == 0) break;
+      return;
+    }
+  }
+  }
+
+  return;
+}
+
+void ASTReader::readAssertRecord(Module &F, uint64_t Offset) {
+  llvm::BitstreamCursor &Stream = F.MacroCursor;
+
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this macro.
+  SavedStreamPosition SavedPosition(Stream);
+
+  Stream.JumpToBit(Offset);
+  RecordData Record;
+  SmallVector<IdentifierInfo*, 16> MacroArgs;
+  AssertionInfo *AI = 0;
+
+  while (true) {
+    unsigned Code = Stream.ReadCode();
+    switch (Code) {
+    case llvm::bitc::END_BLOCK:
+      return;
+
+    case llvm::bitc::ENTER_SUBBLOCK:
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock()) {
+        Error("malformed block record in AST file");
+        return;
+      }
+      continue;
+
+    case llvm::bitc::DEFINE_ABBREV:
+      Stream.ReadAbbrevRecord();
+      continue;
+    default: break;
+    }
+
+    // Read a record.
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    Record.clear();
+    PreprocessorRecordTypes RecType =
+      (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart,
+                                                 BlobLen);
+    switch (RecType) {
+    case PP_ASSERT: {
+      // If we already have an assert, that means that we've hit the end of the
+      // definition of the macro we were looking for. We're done.
+      if (AI)
+        return;
+
+      IdentifierInfo *II = getLocalIdentifier(F, Record[0]);
+      if (II == 0) {
+        Error("assertion must have a predicate name in the AST file");
+        return;
+      }
+
+      SourceLocation Loc = ReadSourceLocation(F, Record[1]);
+      AI = PP.allocateAssertionInfo(Loc);
+      AI->setIsFromAST();
+
+      // Install the assertion
+      PP.addAssertionValue(II, AI);
+
+      // Remember that we saw this assertion last so that we add the tokens
+      // that form its body to it.
+
+      if (Record.size() == 3 && PP.getPreprocessingRecord() &&
+          Record[2]) {
+        // Register the association for the assertion
+        PreprocessedEntityID GlobalID
+          = getGlobalPreprocessedEntityID(F, Record[2]);
+        PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+        PPRec.registerAssertDefinition(II, AI,
+                            PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/ true));
+      }
+
+      ++NumAssertsRead;
+      break;
+    }
+
+    case PP_TOKEN: {
+      // If we see a TOKEN before a PP_ASSERT, then the file is
+      // erroneous, just pretend we didn't see this.
+      if (AI == 0) break;
+
+      Token Tok;
+      Tok.startToken();
+      Tok.setLocation(ReadSourceLocation(F, Record[0]));
+      Tok.setLength(Record[1]);
+      if (IdentifierInfo *II = getLocalIdentifier(F, Record[2]))
+        Tok.setIdentifierInfo(II);
+      Tok.setKind((tok::TokenKind)Record[3]);
+      Tok.setFlag((Token::TokenFlags)Record[4]);
+      AI->AddToken(Tok);
+      break;
+    }
+    case PP_MACRO_FUNCTION_LIKE:
+    case PP_MACRO_OBJECT_LIKE: {
+      if (AI == 0) break;
+      return;
+    }
   }
   }
   
@@ -1463,7 +1587,27 @@
   UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + LocalOffset;
 }
 
+void ASTReader::setIdentifierIsAssert(IdentifierInfo *II, Module &F,
+                                      uint64_t LocalOffset) {
+  // Note that this identifier has an assertion
+  II->setHasAssertedValues(true);
+
+  // Adjust the offset to a global offset.
+  UnreadAssertOffsets[II].push_back(F.GlobalBitOffset + LocalOffset);
+}
+
 void ASTReader::ReadDefinedMacros() {
+  readPreprocessor();
+}
+
+void ASTReader::readAssertions() {
+  readPreprocessor();
+}
+
+void ASTReader::readPreprocessor() {
+  if (PreprocessorRun)
+    return;
+  PreprocessorRun = true;
   for (ModuleReverseIterator I = ModuleMgr.rbegin(),
       E = ModuleMgr.rend(); I != E; ++I) {
     llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
@@ -1506,6 +1650,7 @@
 
       case PP_MACRO_OBJECT_LIKE:
       case PP_MACRO_FUNCTION_LIKE:
+      case PP_ASSERT:
         getLocalIdentifier(**I, Record[0]);
         break;
 
@@ -1519,6 +1664,9 @@
   // Drain the unread macro-record offsets map.
   while (!UnreadMacroRecordOffsets.empty())
     LoadMacroDefinition(UnreadMacroRecordOffsets.begin());
+
+  while (!UnreadAssertOffsets.empty())
+    loadAssertedValues(UnreadAssertOffsets.begin());
 }
 
 void ASTReader::LoadMacroDefinition(
@@ -1537,6 +1685,24 @@
   LoadMacroDefinition(Pos);
 }
 
+void ASTReader::loadAssertedValues(
+            llvm::DenseMap<IdentifierInfo *, AssertOffsetList>::iterator Pos) {
+  assert(Pos != UnreadAssertOffsets.end() && "Unknown assert definition");
+  for (AssertOffsetList::iterator I = Pos->second.begin(),
+                                  E = Pos->second.end(); I != E; ++I) {
+    RecordLocation Loc = getLocalBitOffset(*I);
+    readAssertRecord(*Loc.F, Loc.Offset);
+  }
+  UnreadAssertOffsets.erase(Pos);
+}
+
+void ASTReader::loadAssertedValues(IdentifierInfo *II) {
+  llvm::DenseMap<IdentifierInfo *, AssertOffsetList>::iterator Pos
+    = UnreadAssertOffsets.find(II);
+  if (Pos != UnreadAssertOffsets.end())
+    loadAssertedValues(Pos);
+}
+
 namespace {
   /// \brief Visitor class used to look up identifirs in an AST file.
   class IdentifierLookupVisitor {
@@ -1905,8 +2071,9 @@
     case STATISTICS:
       TotalNumStatements += Record[0];
       TotalNumMacros += Record[1];
-      TotalLexicalDeclContexts += Record[2];
-      TotalVisibleDeclContexts += Record[3];
+      TotalNumAsserts += Record[2];
+      TotalLexicalDeclContexts += Record[3];
+      TotalVisibleDeclContexts += Record[4];
       break;
 
     case UNUSED_FILESCOPED_DECLS:
@@ -2933,6 +3100,15 @@
                                        Range);
     return ID;
   }
+
+  case PPD_ASSERT: {
+    IdentifierInfo *II = getLocalIdentifier(M, Record[0]);
+    AssertDefinition *AD = new (PPRec) AssertDefinition(II, Range);
+
+    if (DeserializationListener)
+      DeserializationListener->assertionRead(PPID, AD);
+    return AD;
+  }
   }
   
   Error("invalid offset in preprocessor detail block");
@@ -4478,6 +4654,10 @@
     std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
                  NumMacrosRead, TotalNumMacros,
                  ((float)NumMacrosRead/TotalNumMacros * 100));
+  if (TotalNumAsserts)
+    std::fprintf(stderr, "  %u/%u asserts read (%f%%)\n",
+                 NumAssertsRead, TotalNumAsserts,
+                 ((float)NumAssertsRead/TotalNumAsserts * 100));
   if (TotalLexicalDeclContexts)
     std::fprintf(stderr, "  %u/%u lexical declcontexts read (%f%%)\n",
                  NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
@@ -5615,12 +5795,13 @@
     DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0), 
     NumSLocEntriesRead(0), TotalNumSLocEntries(0), 
     NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), 
-    TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), 
+    TotalNumMacros(0), NumAssertsRead(0), TotalNumAsserts(0),
+    NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
     NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), 
     NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), 
     NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
     TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
-    NumCXXBaseSpecifiersLoaded(0)
+    NumCXXBaseSpecifiersLoaded(0), PreprocessorRun(false)
 {
   SourceMgr.setExternalSLocEntrySource(this);
 }
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang.orig/lib/Serialization/ASTWriter.cpp	2011-12-13 13:48:57.000000000 +1000
+++ clang/lib/Serialization/ASTWriter.cpp	2011-12-15 15:12:40.337553100 +1000
@@ -811,6 +811,7 @@
   RECORD(PP_MACRO_OBJECT_LIKE);
   RECORD(PP_MACRO_FUNCTION_LIKE);
   RECORD(PP_TOKEN);
+  RECORD(PP_ASSERT);
   
   // Decls and Types block.
   BLOCK(DECLTYPES_BLOCK);
@@ -913,6 +914,7 @@
   RECORD(PPD_MACRO_EXPANSION);
   RECORD(PPD_MACRO_DEFINITION);
   RECORD(PPD_INCLUSION_DIRECTIVE);
+  RECORD(PPD_ASSERT);
   
 #undef RECORD
 #undef BLOCK
@@ -1748,6 +1750,84 @@
     }
     ++NumMacros;
   }
+  // Loop over all the assertions that are live at the end of the file
+  // emitting each to the PP section.
+
+  // Construct the list of assertions that need to be serialized
+  SmallVector<std::pair<const IdentifierInfo *, const AssertionInfo *>, 2>
+    AssertionsToEmit;
+  llvm::SmallPtrSet<const AssertionInfo *, 4> AssertDefinitionsSeen;
+  for (Preprocessor::assertion_iterator I = PP.assertion_begin(Chain == 0),
+                                        E = PP.assertion_end(Chain == 0);
+        I != E; ++I) {
+    for (Preprocessor::assertion_value_iterator AI = I->second.begin(),
+                                                AE = I->second.end();
+          AI != AE; ++AI) {
+      AssertDefinitionsSeen.insert(*AI);
+      AssertionsToEmit.push_back(std::make_pair(I->first, *AI));
+    }
+  }
+
+  // Resolve any identifiers that had asserted values at the time they were
+  // deserialized, adding them to the list of asserts to emit
+  // (if appropriate).
+  for (unsigned I = 0, N = DeserializedAssertPredicates.size(); I != N; ++I){
+    IdentifierInfo *Name
+      = const_cast<IdentifierInfo *>(DeserializedAssertPredicates[I]);
+    if (Name->hasAssertedValues()) {
+      for (Preprocessor::assertion_value_iterator
+           VI = PP.getAssertionsBegin(Name), VE = PP.getAssertionsEnd(Name);
+           VI != VE; ++VI) {
+        if (AssertDefinitionsSeen.insert(*VI))
+          AssertionsToEmit.push_back(std::make_pair(Name, *VI));
+      }
+    }
+  }
+
+  for (unsigned I = 0, N = AssertionsToEmit.size(); I != N; ++I) {
+    const IdentifierInfo *Pred = AssertionsToEmit[I].first;
+    const AssertionInfo *AI = AssertionsToEmit[I].second;
+    if (!AI)
+      continue;
+
+    if (Chain && Pred->isFromAST() && !Pred->hasChangedSinceDeserialization())
+      continue;
+
+    AddIdentifierRef(Pred, Record);
+    AssertOffsets[Pred].push_back(Stream.GetCurrentBitNo());
+    Record.push_back(AI->getAssertionLoc().getRawEncoding());
+
+    // If we have a detailed preprocessing record, record the assertion definition
+    // ID that corresponds to this assertion
+    if (PPRec)
+      Record.push_back(AssertDefinitions[PPRec->findAssertDefinition(Pred, AI)]);
+
+    Stream.EmitRecord(PP_ASSERT, Record);
+    Record.clear();
+
+    // Emit the tokens array.
+    for (unsigned TokNo = 0, E = AI->getNumTokens(); TokNo != E; ++TokNo) {
+      // Note that we know the preprocessor does not have any annotation
+      // tokens in it because they are created by the parser and thus can't
+      // be in an assert value
+      const Token &Tok = AI->getValueToken(TokNo);
+
+      Record.push_back(Tok.getLocation().getRawEncoding());
+      Record.push_back(Tok.getLength());
+
+      // FIXME: When reading literal tokens, reconstruct the literal pointer if
+      // it is needed.
+      AddIdentifierRef(Tok.getIdentifierInfo(), Record);
+      // FIXME: Should translate token kind to a stable encoding.
+      Record.push_back(Tok.getKind());
+      // FIXME: Should translate token flags to a stable encoding.
+      Record.push_back(Tok.getFlags());
+
+      Stream.EmitRecord(PP_TOKEN, Record);
+      Record.clear();
+    }
+    ++NumAsserts;
+  }
   Stream.ExitBlock();
 }
 
@@ -1820,6 +1900,16 @@
       Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
       continue;
     }
+
+    if (AssertDefinition *AD = dyn_cast<AssertDefinition>(*E)) {
+      Record.push_back(PPD_ASSERT);
+      // Record this assertion's ID.
+      AssertDefinitions[AD] = NextPreprocessorEntityID;
+
+      AddIdentifierRef(AD->getName(), Record);
+      Stream.EmitRecord(PPD_ASSERT, Record);
+      continue;
+    }
     
     llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
   }
@@ -2254,7 +2344,8 @@
         II->isExtensionToken() ||
         II->getObjCOrBuiltinID() ||
         II->hasRevertedTokenIDToIdentifier() ||
-        II->getFETokenInfo<void>())
+        II->getFETokenInfo<void>() ||
+        II->hasAssertedValues())
       return true;
 
     return hasMacroDefinition(II, Macro);
@@ -2291,9 +2382,13 @@
     unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
     MacroInfo *Macro = 0;
     if (isInterestingIdentifier(II, Macro)) {
-      DataLen += 2; // 2 bytes for builtin ID, flags
+      DataLen += 4; // 4 bytes for builtin ID, flags
       if (hasMacroDefinition(II, Macro))
         DataLen += 4;
+      if (II->hasAssertedValues())
+         // 2 bytes for the number of asserts
+         // 4 bytes for each assert value ID
+        DataLen += 2 + (4 * Writer.getNumAssertValues(II));
       
       for (IdentifierResolver::iterator D = IdResolver.begin(II),
                                      DEnd = IdResolver.end();
@@ -2333,10 +2428,21 @@
     Bits = (Bits << 1) | unsigned(II->isPoisoned());
     Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
     Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
-    clang::io::Emit16(Out, Bits);
+    Bits = (Bits << 1) | unsigned(II->hasAssertedValues());
+    clang::io::Emit32(Out, Bits);
 
     if (HasMacroDefinition)
       clang::io::Emit32(Out, Writer.getMacroOffset(II));
+    if (II->hasAssertedValues()) {
+      // the number of asserted values
+      clang::io::Emit16(Out, Writer.getNumAssertValues(II));
+
+      // emit the references to the asserted values
+      const ASTWriter::AssertOffsetList *Values = Writer.getAssertOffsets(II);
+      for (ASTWriter::AssertOffsetList::const_iterator
+        I = Values->begin(), E = Values->end(); I != E; ++I)
+        clang::io::Emit32(Out, *I);
+    }
 
     // Emit the declaration IDs in reverse order, because the
     // IdentifierResolver provides the declarations as they would be
@@ -3183,6 +3289,7 @@
   Record.clear();
   Record.push_back(NumStatements);
   Record.push_back(NumMacros);
+  Record.push_back(NumAsserts);
   Record.push_back(NumLexicalDeclContexts);
   Record.push_back(NumVisibleDeclContexts);
   Stream.EmitRecord(STATISTICS, Record);
@@ -3990,6 +4097,8 @@
   IdentifierIDs[II] = ID;
   if (II->hasMacroDefinition())
     DeserializedMacroNames.push_back(II);
+  if (II->hasAssertedValues())
+    DeserializedAssertPredicates.push_back(II);
 }
 
 void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {
@@ -4017,6 +4126,12 @@
   MacroDefinitions[MD] = ID;
 }
 
+void ASTWriter::assertionRead(serialization::PreprocessedEntityID ID,
+                              AssertDefinition *AD) {
+  assert(AssertDefinitions.find(AD) == AssertDefinitions.end());
+  AssertDefinitions[AD] = ID;
+}
+
 void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
   assert(D->isCompleteDefinition());
   assert(!WritingAST && "Already writing the AST!");
Index: clang/test/PCH/Inputs/chain-assert1.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/test/PCH/Inputs/chain-assert1.h	2011-12-15 06:28:41.666987100 +1000
@@ -0,0 +1 @@
+#assert x(1)
Index: clang/test/PCH/Inputs/chain-assert2.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/test/PCH/Inputs/chain-assert2.h	2011-12-15 06:28:42.856055100 +1000
@@ -0,0 +1 @@
+#assert x(2)
Index: clang/test/PCH/chain-assert.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ clang/test/PCH/chain-assert.c	2011-12-15 14:23:18.105397400 +1000
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -emit-pch -o %t1 -detailed-preprocessing-record %S/Inputs/chain-assert1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 -detailed-preprocessing-record %S/Inputs/chain-assert2.h -include-pch %t1
+// RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s
+// RUN: %clang_cc1 -ast-print -include-pch %t2 %s | FileCheck %s
+
+
+int main() {
+// CHECK: return 0;
+#if #x(1) && #x(2)
+return 0;
+#else
+return 1;
+#endif
+}
\ No newline at end of file
