Check in LLVM r95781.
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
new file mode 100644
index 0000000..33cb94e
--- /dev/null
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -0,0 +1,609 @@
+//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// AST Consumer Implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "llvm/Module.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+/// ASTPrinter - Pretty-printer and dumper of ASTs
+
+namespace {
+  class ASTPrinter : public ASTConsumer {
+    llvm::raw_ostream &Out;
+    bool Dump;
+
+  public:
+    ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
+      : Out(o? *o : llvm::errs()), Dump(Dump) { }
+
+    virtual void HandleTranslationUnit(ASTContext &Context) {
+      PrintingPolicy Policy = Context.PrintingPolicy;
+      Policy.Dump = Dump;
+      Context.getTranslationUnitDecl()->print(Out, Policy);
+    }
+  };
+} // end anonymous namespace
+
+ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
+  return new ASTPrinter(out);
+}
+
+//===----------------------------------------------------------------------===//
+/// ASTPrinterXML - XML-printer of ASTs
+
+namespace {
+  class ASTPrinterXML : public ASTConsumer {
+    DocumentXML         Doc;
+
+  public:
+    ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
+
+    void Initialize(ASTContext &Context) {
+      Doc.initialize(Context);
+    }
+
+    virtual void HandleTranslationUnit(ASTContext &Ctx) {
+      Doc.addSubNode("TranslationUnit");
+      for (DeclContext::decl_iterator
+             D = Ctx.getTranslationUnitDecl()->decls_begin(),
+             DEnd = Ctx.getTranslationUnitDecl()->decls_end();
+           D != DEnd;
+           ++D)
+        Doc.PrintDecl(*D);
+      Doc.toParent();
+      Doc.finalize();
+    }
+  };
+} // end anonymous namespace
+
+
+ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
+  return new ASTPrinterXML(out ? *out : llvm::outs());
+}
+
+ASTConsumer *clang::CreateASTDumper() {
+  return new ASTPrinter(0, true);
+}
+
+//===----------------------------------------------------------------------===//
+/// ASTViewer - AST Visualization
+
+namespace {
+  class ASTViewer : public ASTConsumer {
+    ASTContext *Context;
+  public:
+    void Initialize(ASTContext &Context) {
+      this->Context = &Context;
+    }
+
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        HandleTopLevelSingleDecl(*I);
+    }
+
+    void HandleTopLevelSingleDecl(Decl *D);
+  };
+}
+
+void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    FD->print(llvm::errs());
+
+    if (Stmt *Body = FD->getBody()) {
+      llvm::errs() << '\n';
+      Body->viewAST();
+      llvm::errs() << '\n';
+    }
+    return;
+  }
+
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    MD->print(llvm::errs());
+
+    if (MD->getBody()) {
+      llvm::errs() << '\n';
+      MD->getBody()->viewAST();
+      llvm::errs() << '\n';
+    }
+  }
+}
+
+
+ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
+
+//===----------------------------------------------------------------------===//
+/// DeclContextPrinter - Decl and DeclContext Visualization
+
+namespace {
+
+class DeclContextPrinter : public ASTConsumer {
+  llvm::raw_ostream& Out;
+public:
+  DeclContextPrinter() : Out(llvm::errs()) {}
+
+  void HandleTranslationUnit(ASTContext &C) {
+    PrintDeclContext(C.getTranslationUnitDecl(), 4);
+  }
+
+  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
+};
+}  // end anonymous namespace
+
+void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
+                                          unsigned Indentation) {
+  // Print DeclContext name.
+  switch (DC->getDeclKind()) {
+  case Decl::TranslationUnit:
+    Out << "[translation unit] " << DC;
+    break;
+  case Decl::Namespace: {
+    Out << "[namespace] ";
+    const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
+    Out << ND->getNameAsString();
+    break;
+  }
+  case Decl::Enum: {
+    const EnumDecl* ED = cast<EnumDecl>(DC);
+    if (ED->isDefinition())
+      Out << "[enum] ";
+    else
+      Out << "<enum> ";
+    Out << ED->getNameAsString();
+    break;
+  }
+  case Decl::Record: {
+    const RecordDecl* RD = cast<RecordDecl>(DC);
+    if (RD->isDefinition())
+      Out << "[struct] ";
+    else
+      Out << "<struct> ";
+    Out << RD->getNameAsString();
+    break;
+  }
+  case Decl::CXXRecord: {
+    const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
+    if (RD->isDefinition())
+      Out << "[class] ";
+    else
+      Out << "<class> ";
+    Out << RD->getNameAsString() << " " << DC;
+    break;
+  }
+  case Decl::ObjCMethod:
+    Out << "[objc method]";
+    break;
+  case Decl::ObjCInterface:
+    Out << "[objc interface]";
+    break;
+  case Decl::ObjCCategory:
+    Out << "[objc category]";
+    break;
+  case Decl::ObjCProtocol:
+    Out << "[objc protocol]";
+    break;
+  case Decl::ObjCImplementation:
+    Out << "[objc implementation]";
+    break;
+  case Decl::ObjCCategoryImpl:
+    Out << "[objc categoryimpl]";
+    break;
+  case Decl::LinkageSpec:
+    Out << "[linkage spec]";
+    break;
+  case Decl::Block:
+    Out << "[block]";
+    break;
+  case Decl::Function: {
+    const FunctionDecl* FD = cast<FunctionDecl>(DC);
+    if (FD->isThisDeclarationADefinition())
+      Out << "[function] ";
+    else
+      Out << "<function> ";
+    Out << FD->getNameAsString();
+    // Print the parameters.
+    Out << "(";
+    bool PrintComma = false;
+    for (FunctionDecl::param_const_iterator I = FD->param_begin(),
+           E = FD->param_end(); I != E; ++I) {
+      if (PrintComma)
+        Out << ", ";
+      else
+        PrintComma = true;
+      Out << (*I)->getNameAsString();
+    }
+    Out << ")";
+    break;
+  }
+  case Decl::CXXMethod: {
+    const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
+    if (D->isOutOfLine())
+      Out << "[c++ method] ";
+    else if (D->isImplicit())
+      Out << "(c++ method) ";
+    else
+      Out << "<c++ method> ";
+    Out << D->getNameAsString();
+    // Print the parameters.
+    Out << "(";
+    bool PrintComma = false;
+    for (FunctionDecl::param_const_iterator I = D->param_begin(),
+           E = D->param_end(); I != E; ++I) {
+      if (PrintComma)
+        Out << ", ";
+      else
+        PrintComma = true;
+      Out << (*I)->getNameAsString();
+    }
+    Out << ")";
+
+    // Check the semantic DeclContext.
+    const DeclContext* SemaDC = D->getDeclContext();
+    const DeclContext* LexicalDC = D->getLexicalDeclContext();
+    if (SemaDC != LexicalDC)
+      Out << " [[" << SemaDC << "]]";
+
+    break;
+  }
+  case Decl::CXXConstructor: {
+    const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
+    if (D->isOutOfLine())
+      Out << "[c++ ctor] ";
+    else if (D->isImplicit())
+      Out << "(c++ ctor) ";
+    else
+      Out << "<c++ ctor> ";
+    Out << D->getNameAsString();
+    // Print the parameters.
+    Out << "(";
+    bool PrintComma = false;
+    for (FunctionDecl::param_const_iterator I = D->param_begin(),
+           E = D->param_end(); I != E; ++I) {
+      if (PrintComma)
+        Out << ", ";
+      else
+        PrintComma = true;
+      Out << (*I)->getNameAsString();
+    }
+    Out << ")";
+
+    // Check the semantic DC.
+    const DeclContext* SemaDC = D->getDeclContext();
+    const DeclContext* LexicalDC = D->getLexicalDeclContext();
+    if (SemaDC != LexicalDC)
+      Out << " [[" << SemaDC << "]]";
+    break;
+  }
+  case Decl::CXXDestructor: {
+    const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
+    if (D->isOutOfLine())
+      Out << "[c++ dtor] ";
+    else if (D->isImplicit())
+      Out << "(c++ dtor) ";
+    else
+      Out << "<c++ dtor> ";
+    Out << D->getNameAsString();
+    // Check the semantic DC.
+    const DeclContext* SemaDC = D->getDeclContext();
+    const DeclContext* LexicalDC = D->getLexicalDeclContext();
+    if (SemaDC != LexicalDC)
+      Out << " [[" << SemaDC << "]]";
+    break;
+  }
+  case Decl::CXXConversion: {
+    const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
+    if (D->isOutOfLine())
+      Out << "[c++ conversion] ";
+    else if (D->isImplicit())
+      Out << "(c++ conversion) ";
+    else
+      Out << "<c++ conversion> ";
+    Out << D->getNameAsString();
+    // Check the semantic DC.
+    const DeclContext* SemaDC = D->getDeclContext();
+    const DeclContext* LexicalDC = D->getLexicalDeclContext();
+    if (SemaDC != LexicalDC)
+      Out << " [[" << SemaDC << "]]";
+    break;
+  }
+
+  default:
+    assert(0 && "a decl that inherits DeclContext isn't handled");
+  }
+
+  Out << "\n";
+
+  // Print decls in the DeclContext.
+  for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+       I != E; ++I) {
+    for (unsigned i = 0; i < Indentation; ++i)
+      Out << "  ";
+
+    Decl::Kind DK = I->getKind();
+    switch (DK) {
+    case Decl::Namespace:
+    case Decl::Enum:
+    case Decl::Record:
+    case Decl::CXXRecord:
+    case Decl::ObjCMethod:
+    case Decl::ObjCInterface:
+    case Decl::ObjCCategory:
+    case Decl::ObjCProtocol:
+    case Decl::ObjCImplementation:
+    case Decl::ObjCCategoryImpl:
+    case Decl::LinkageSpec:
+    case Decl::Block:
+    case Decl::Function:
+    case Decl::CXXMethod:
+    case Decl::CXXConstructor:
+    case Decl::CXXDestructor:
+    case Decl::CXXConversion:
+    {
+      DeclContext* DC = cast<DeclContext>(*I);
+      PrintDeclContext(DC, Indentation+2);
+      break;
+    }
+    case Decl::Field: {
+      FieldDecl* FD = cast<FieldDecl>(*I);
+      Out << "<field> " << FD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::Typedef: {
+      TypedefDecl* TD = cast<TypedefDecl>(*I);
+      Out << "<typedef> " << TD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::EnumConstant: {
+      EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
+      Out << "<enum constant> " << ECD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::Var: {
+      VarDecl* VD = cast<VarDecl>(*I);
+      Out << "<var> " << VD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ImplicitParam: {
+      ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
+      Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ParmVar: {
+      ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
+      Out << "<parameter> " << PVD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ObjCProperty: {
+      ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
+      Out << "<objc property> " << OPD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::FunctionTemplate: {
+      FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
+      Out << "<function template> " << FTD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::FileScopeAsm: {
+      Out << "<file-scope asm>\n";
+      break;
+    }
+    case Decl::UsingDirective: {
+      Out << "<using directive>\n";
+      break;
+    }
+    case Decl::NamespaceAlias: {
+      NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
+      Out << "<namespace alias> " << NAD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ClassTemplate: {
+      ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
+      Out << "<class template> " << CTD->getNameAsString() << '\n';
+      break;
+    }
+    default:
+      Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
+      assert(0 && "decl unhandled");
+    }
+  }
+}
+ASTConsumer *clang::CreateDeclContextPrinter() {
+  return new DeclContextPrinter();
+}
+
+//===----------------------------------------------------------------------===//
+/// RecordLayoutDumper - C++ Record Layout Dumping.
+namespace {
+class RecordLayoutDumper : public ASTConsumer {
+  llvm::raw_ostream& Out;
+  
+  void PrintOffset(uint64_t Offset, unsigned IndentLevel) {
+    Out << llvm::format("%4d | ", Offset);
+    for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' ';
+  }
+  
+  void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C,
+                               uint64_t Offset,
+                               unsigned IndentLevel, const char* Description,
+                               bool IncludeVirtualBases) {
+    const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
+
+    PrintOffset(Offset, IndentLevel);
+    Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString();
+    if (Description)
+      Out << ' ' << Description;
+    if (RD->isEmpty())
+      Out << " (empty)";
+    Out << '\n';
+    
+    IndentLevel++;
+    
+    const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase();
+    
+    // Vtable pointer.
+    if (RD->isDynamicClass() && !PrimaryBase) {
+      PrintOffset(Offset, IndentLevel);
+      Out << '(' << RD->getNameAsString() << " vtable pointer)\n";
+    }
+    // Dump (non-virtual) bases
+    for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+         E = RD->bases_end(); I != E; ++I) {
+      assert(!I->getType()->isDependentType() &&
+             "Cannot layout class with dependent bases.");
+      if (I->isVirtual())
+        continue;
+      
+      const CXXRecordDecl *Base =
+        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+      
+      uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8;
+      
+      DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel, 
+                              Base == PrimaryBase ? "(primary base)" : "(base)",
+                              /*IncludeVirtualBases=*/false);
+    }
+    
+    // Dump fields.
+    uint64_t FieldNo = 0;
+    for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+         E = RD->field_end(); I != E; ++I, ++FieldNo) {      
+      const FieldDecl *Field = *I;
+      uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8;
+      
+      if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
+        if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+          DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel, 
+                                  Field->getNameAsCString(),
+                                  /*IncludeVirtualBases=*/true);
+          continue;
+        }
+      }
+      
+      PrintOffset(FieldOffset, IndentLevel);
+      Out << Field->getType().getAsString() << ' ';
+      Out << Field->getNameAsString() << '\n';
+    }
+    
+    if (!IncludeVirtualBases)
+      return;
+    
+    // Dump virtual bases.
+    for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+         E = RD->vbases_end(); I != E; ++I) {
+      assert(I->isVirtual() && "Found non-virtual class!");
+      const CXXRecordDecl *VBase =
+        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+      
+      uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8;
+      DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel, 
+                              VBase == PrimaryBase ? 
+                              "(primary virtual base)" : "(virtual base)",
+                              /*IncludeVirtualBases=*/false);
+    }
+  }
+  
+  // FIXME: Maybe this could be useful in ASTContext.cpp.
+  void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) {
+    const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
+    
+    DumpRecordLayoutOffsets(RD, C, 0, 0, 0, 
+                            /*IncludeVirtualBases=*/true);
+    Out << "  sizeof=" << Info.getSize() / 8;
+    Out << ", dsize=" << Info.getDataSize() / 8;
+    Out << ", align=" << Info.getAlignment() / 8 << '\n';
+    Out << "  nvsize=" << Info.getNonVirtualSize() / 8;
+    Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n';
+    Out << '\n';
+  }
+  
+public:
+  RecordLayoutDumper() : Out(llvm::errs()) {}
+  
+  void HandleTranslationUnit(ASTContext &C) {
+    for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end(); 
+         I != E; ++I) {
+      const RecordType *RT = dyn_cast<RecordType>(*I);
+      if (!RT)
+        continue;
+      
+      const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+      if (!RD)
+        continue;
+      
+      if (RD->isImplicit())
+        continue;
+
+      if (RD->isDependentType())
+        continue;
+      
+      if (RD->isInvalidDecl())
+        continue;
+      
+      if (!RD->getDefinition(C))
+        continue;
+      
+      // FIXME: Do we really need to hard code this?
+      if (RD->getQualifiedNameAsString() == "__va_list_tag")
+        continue;
+      
+      DumpRecordLayout(RD, C);
+   }
+  }
+};
+} // end anonymous namespace
+ASTConsumer *clang::CreateRecordLayoutDumper() {
+  return new RecordLayoutDumper();
+}
+
+//===----------------------------------------------------------------------===//
+/// InheritanceViewer - C++ Inheritance Visualization
+
+namespace {
+class InheritanceViewer : public ASTConsumer {
+  const std::string clsname;
+public:
+  InheritanceViewer(const std::string& cname) : clsname(cname) {}
+
+  void HandleTranslationUnit(ASTContext &C) {
+    for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
+      if (RecordType *T = dyn_cast<RecordType>(*I)) {
+        if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
+          // FIXME: This lookup needs to be generalized to handle namespaces and
+          // (when we support them) templates.
+          if (D->getNameAsString() == clsname) {
+            D->viewInheritance(C);
+          }
+        }
+      }
+  }
+};
+}
+
+ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
+  return new InheritanceViewer(clsname);
+}
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
new file mode 100644
index 0000000..d51647b
--- /dev/null
+++ b/lib/Frontend/ASTMerge.cpp
@@ -0,0 +1,107 @@
+//===-- ASTMerge.cpp - AST Merging Frontent Action --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTImporter.h"
+
+using namespace clang;
+
+ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI,
+                                               llvm::StringRef InFile) {
+  return AdaptedAction->CreateASTConsumer(CI, InFile);
+}
+
+bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI,
+                                           llvm::StringRef Filename) {
+  // FIXME: This is a hack. We need a better way to communicate the
+  // AST file, compiler instance, and file name than member variables
+  // of FrontendAction.
+  AdaptedAction->setCurrentFile(getCurrentFile(), takeCurrentASTUnit());
+  AdaptedAction->setCompilerInstance(&CI);
+  return AdaptedAction->BeginSourceFileAction(CI, Filename);
+}
+
+void ASTMergeAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+  CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
+                                       &CI.getASTContext());
+  for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
+    Diagnostic ASTDiags(CI.getDiagnostics().getClient());
+    
+    ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], ASTDiags,
+                                             false, true);
+    if (!Unit)
+      continue;
+
+    ASTDiags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
+                              &Unit->getASTContext());
+    ASTImporter Importer(CI.getASTContext(), 
+                         CI.getFileManager(),
+                         CI.getDiagnostics(),
+                         Unit->getASTContext(), 
+                         Unit->getFileManager(),
+                         ASTDiags);
+
+    TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
+    for (DeclContext::decl_iterator D = TU->decls_begin(), 
+                                 DEnd = TU->decls_end();
+         D != DEnd; ++D) {
+      // FIXME: We only merge variables whose names start with x. Why
+      // would anyone want anything else?
+      if (VarDecl *VD = dyn_cast<VarDecl>(*D))
+        if (VD->getIdentifier() && 
+            *VD->getIdentifier()->getNameStart() == 'x') {
+          Decl *Merged = Importer.Import(VD);
+          (void)Merged;
+        }
+    }
+
+    delete Unit;
+  }
+
+
+  return AdaptedAction->ExecuteAction();
+}
+
+void ASTMergeAction::EndSourceFileAction() {
+  return AdaptedAction->EndSourceFileAction();
+}
+
+ASTMergeAction::ASTMergeAction(FrontendAction *AdaptedAction,
+                               std::string *ASTFiles, unsigned NumASTFiles)
+  : AdaptedAction(AdaptedAction), ASTFiles(ASTFiles, ASTFiles + NumASTFiles) {
+  assert(AdaptedAction && "ASTMergeAction needs an action to adapt");
+}
+
+ASTMergeAction::~ASTMergeAction() { 
+  delete AdaptedAction;
+}
+
+bool ASTMergeAction::usesPreprocessorOnly() const {
+  return AdaptedAction->usesPreprocessorOnly();
+}
+
+bool ASTMergeAction::usesCompleteTranslationUnit() {
+  return AdaptedAction->usesCompleteTranslationUnit();
+}
+
+bool ASTMergeAction::hasPCHSupport() const {
+  return AdaptedAction->hasPCHSupport();
+}
+
+bool ASTMergeAction::hasASTSupport() const {
+  return AdaptedAction->hasASTSupport();
+}
+
+bool ASTMergeAction::hasCodeCompletionSupport() const {
+  return AdaptedAction->hasCodeCompletionSupport();
+}
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
new file mode 100644
index 0000000..7f1e722
--- /dev/null
+++ b/lib/Frontend/ASTUnit.cpp
@@ -0,0 +1,372 @@
+//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit Implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Path.h"
+using namespace clang;
+
+ASTUnit::ASTUnit(bool _MainFileIsAST)
+  : tempFile(false), MainFileIsAST(_MainFileIsAST) {
+}
+ASTUnit::~ASTUnit() {
+  if (tempFile)
+    llvm::sys::Path(getPCHFileName()).eraseFromDisk();
+}
+
+namespace {
+
+/// \brief Gathers information from PCHReader that will be used to initialize
+/// a Preprocessor.
+class PCHInfoCollector : public PCHReaderListener {
+  LangOptions &LangOpt;
+  HeaderSearch &HSI;
+  std::string &TargetTriple;
+  std::string &Predefines;
+  unsigned &Counter;
+
+  unsigned NumHeaderInfos;
+
+public:
+  PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
+                   std::string &TargetTriple, std::string &Predefines,
+                   unsigned &Counter)
+    : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
+      Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
+
+  virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+    LangOpt = LangOpts;
+    return false;
+  }
+
+  virtual bool ReadTargetTriple(llvm::StringRef Triple) {
+    TargetTriple = Triple;
+    return false;
+  }
+
+  virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
+                                    FileID PCHBufferID,
+                                    llvm::StringRef OriginalFileName,
+                                    std::string &SuggestedPredefines) {
+    Predefines = PCHPredef;
+    return false;
+  }
+
+  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+    HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+  }
+
+  virtual void ReadCounter(unsigned Value) {
+    Counter = Value;
+  }
+};
+
+} // anonymous namespace
+
+const std::string &ASTUnit::getOriginalSourceFileName() {
+  return OriginalSourceFile;
+}
+
+const std::string &ASTUnit::getPCHFileName() {
+  assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
+  return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
+}
+
+ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
+                                  Diagnostic &Diags,
+                                  bool OnlyLocalDecls,
+                                  bool UseBumpAllocator,
+                                  RemappedFile *RemappedFiles,
+                                  unsigned NumRemappedFiles) {
+  llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
+  AST->OnlyLocalDecls = OnlyLocalDecls;
+  AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
+
+  for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile
+      = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
+                                    RemappedFiles[I].second->getBufferSize(),
+                                             0);
+    if (!FromFile) {
+      Diags.Report(diag::err_fe_remap_missing_from_file)
+        << RemappedFiles[I].first;
+      continue;
+    }
+    
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    AST->getSourceManager().overrideFileContents(FromFile, 
+                                                 RemappedFiles[I].second);    
+  }
+  
+  // Gather Info for preprocessor construction later on.
+
+  LangOptions LangInfo;
+  HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
+  std::string TargetTriple;
+  std::string Predefines;
+  unsigned Counter;
+
+  llvm::OwningPtr<PCHReader> Reader;
+  llvm::OwningPtr<ExternalASTSource> Source;
+
+  Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
+                             Diags));
+  Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
+                                           Predefines, Counter));
+
+  switch (Reader->ReadPCH(Filename)) {
+  case PCHReader::Success:
+    break;
+
+  case PCHReader::Failure:
+  case PCHReader::IgnorePCH:
+    Diags.Report(diag::err_fe_unable_to_load_pch);
+    return NULL;
+  }
+
+  AST->OriginalSourceFile = Reader->getOriginalSourceFile();
+
+  // PCH loaded successfully. Now create the preprocessor.
+
+  // Get information about the target being compiled for.
+  //
+  // FIXME: This is broken, we should store the TargetOptions in the PCH.
+  TargetOptions TargetOpts;
+  TargetOpts.ABI = "";
+  TargetOpts.CPU = "";
+  TargetOpts.Features.clear();
+  TargetOpts.Triple = TargetTriple;
+  AST->Target.reset(TargetInfo::CreateTargetInfo(Diags, TargetOpts));
+  AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(),
+                                 AST->getSourceManager(), HeaderInfo));
+  Preprocessor &PP = *AST->PP.get();
+
+  PP.setPredefines(Reader->getSuggestedPredefines());
+  PP.setCounterValue(Counter);
+  Reader->setPreprocessor(PP);
+
+  // Create and initialize the ASTContext.
+
+  AST->Ctx.reset(new ASTContext(LangInfo,
+                                AST->getSourceManager(),
+                                *AST->Target.get(),
+                                PP.getIdentifierTable(),
+                                PP.getSelectorTable(),
+                                PP.getBuiltinInfo(),
+                                /* FreeMemory = */ !UseBumpAllocator,
+                                /* size_reserve = */0));
+  ASTContext &Context = *AST->Ctx.get();
+
+  Reader->InitializeContext(Context);
+
+  // Attach the PCH reader to the AST context as an external AST
+  // source, so that declarations will be deserialized from the
+  // PCH file as needed.
+  Source.reset(Reader.take());
+  Context.setExternalSource(Source);
+
+  return AST.take();
+}
+
+namespace {
+
+class TopLevelDeclTrackerConsumer : public ASTConsumer {
+  ASTUnit &Unit;
+
+public:
+  TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
+
+  void HandleTopLevelDecl(DeclGroupRef D) {
+    for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
+      Unit.getTopLevelDecls().push_back(*it);
+  }
+};
+
+class TopLevelDeclTrackerAction : public ASTFrontendAction {
+public:
+  ASTUnit &Unit;
+
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         llvm::StringRef InFile) {
+    return new TopLevelDeclTrackerConsumer(Unit);
+  }
+
+public:
+  TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
+
+  virtual bool hasCodeCompletionSupport() const { return false; }
+};
+
+}
+
+ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI,
+                                             Diagnostic &Diags,
+                                             bool OnlyLocalDecls) {
+  // Create the compiler instance to use for building the AST.
+  CompilerInstance Clang;
+  llvm::OwningPtr<ASTUnit> AST;
+  llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
+
+  Clang.setInvocation(const_cast<CompilerInvocation*>(&CI));
+
+  Clang.setDiagnostics(&Diags);
+  Clang.setDiagnosticClient(Diags.getClient());
+
+  // Create the target instance.
+  Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
+                                               Clang.getTargetOpts()));
+  if (!Clang.hasTarget())
+    goto error;
+
+  // Inform the target of the language options.
+  //
+  // FIXME: We shouldn't need to do this, the target should be immutable once
+  // created. This complexity should be lifted elsewhere.
+  Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
+
+  assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
+         "Invocation must have exactly one source file!");
+  assert(Clang.getFrontendOpts().Inputs[0].first != FrontendOptions::IK_AST &&
+         "FIXME: AST inputs not yet supported here!");
+
+  // Create the AST unit.
+  AST.reset(new ASTUnit(false));
+
+  AST->OnlyLocalDecls = OnlyLocalDecls;
+  AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+  // Create a file manager object to provide access to and cache the filesystem.
+  Clang.setFileManager(&AST->getFileManager());
+
+  // Create the source manager.
+  Clang.setSourceManager(&AST->getSourceManager());
+
+  // Create the preprocessor.
+  Clang.createPreprocessor();
+
+  Act.reset(new TopLevelDeclTrackerAction(*AST));
+  if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+                           /*IsAST=*/false))
+    goto error;
+
+  Act->Execute();
+
+  // Steal the created target, context, and preprocessor, and take back the
+  // source and file managers.
+  AST->Ctx.reset(Clang.takeASTContext());
+  AST->PP.reset(Clang.takePreprocessor());
+  Clang.takeSourceManager();
+  Clang.takeFileManager();
+  AST->Target.reset(Clang.takeTarget());
+
+  Act->EndSourceFile();
+
+  Clang.takeDiagnosticClient();
+  Clang.takeDiagnostics();
+  Clang.takeInvocation();
+
+  return AST.take();
+
+error:
+  Clang.takeSourceManager();
+  Clang.takeFileManager();
+  Clang.takeDiagnosticClient();
+  Clang.takeDiagnostics();
+  return 0;
+}
+
+ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
+                                      const char **ArgEnd,
+                                      Diagnostic &Diags,
+                                      llvm::StringRef ResourceFilesPath,
+                                      bool OnlyLocalDecls,
+                                      bool UseBumpAllocator,
+                                      RemappedFile *RemappedFiles,
+                                      unsigned NumRemappedFiles) {
+  llvm::SmallVector<const char *, 16> Args;
+  Args.push_back("<clang>"); // FIXME: Remove dummy argument.
+  Args.insert(Args.end(), ArgBegin, ArgEnd);
+
+  // FIXME: Find a cleaner way to force the driver into restricted modes. We
+  // also want to force it to use clang.
+  Args.push_back("-fsyntax-only");
+
+  // FIXME: We shouldn't have to pass in the path info.
+  driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(),
+                           "a.out", false, Diags);
+
+  // Don't check that inputs exist, they have been remapped.
+  TheDriver.setCheckInputsExist(false);
+
+  llvm::OwningPtr<driver::Compilation> C(
+    TheDriver.BuildCompilation(Args.size(), Args.data()));
+
+  // We expect to get back exactly one command job, if we didn't something
+  // failed.
+  const driver::JobList &Jobs = C->getJobs();
+  if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
+    llvm::SmallString<256> Msg;
+    llvm::raw_svector_ostream OS(Msg);
+    C->PrintJob(OS, C->getJobs(), "; ", true);
+    Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
+    return 0;
+  }
+
+  const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
+  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+    Diags.Report(diag::err_fe_expected_clang_command);
+    return 0;
+  }
+
+  const driver::ArgStringList &CCArgs = Cmd->getArguments();
+  llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
+  CompilerInvocation::CreateFromArgs(*CI, (const char**) CCArgs.data(),
+                                     (const char**) CCArgs.data()+CCArgs.size(),
+                                     Diags);
+
+  // Override any files that need remapping
+  for (unsigned I = 0; I != NumRemappedFiles; ++I)
+    CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+                                             RemappedFiles[I].second);
+  
+  // Override the resources path.
+  CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
+
+  CI->getFrontendOpts().DisableFree = UseBumpAllocator;
+  ASTUnit *Unit = LoadFromCompilerInvocation(*CI, Diags, OnlyLocalDecls);
+  if (Unit)
+    Unit->Invocation.reset(CI.take());
+
+  return Unit;
+}
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
new file mode 100644
index 0000000..84f0157
--- /dev/null
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -0,0 +1,658 @@
+//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// "Meta" ASTConsumer for running different source analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Analyses/UninitializedValues.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Checker/Checkers/LocalCheckers.h"
+#include "clang/Checker/ManagerRegistry.h"
+#include "clang/Checker/BugReporter/PathDiagnostic.h"
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
+#include "clang/Checker/PathSensitive/GRExprEngine.h"
+#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
+#include "llvm/ADT/OwningPtr.h"
+
+using namespace clang;
+
+static ExplodedNode::Auditor* CreateUbiViz();
+
+//===----------------------------------------------------------------------===//
+// Basic type definitions.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Special PathDiagnosticClients.
+//===----------------------------------------------------------------------===//
+
+static PathDiagnosticClient*
+CreatePlistHTMLDiagnosticClient(const std::string& prefix,
+                                const Preprocessor &PP) {
+  llvm::sys::Path F(prefix);
+  PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP);
+  return CreatePlistDiagnosticClient(prefix, PP, PD);
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer declaration.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+ class AnalysisConsumer : public ASTConsumer {
+ public:
+  typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
+   
+ private:
+  typedef std::vector<CodeAction> Actions;
+  Actions FunctionActions;
+  Actions ObjCMethodActions;
+  Actions ObjCImplementationActions;
+  Actions TranslationUnitActions;
+
+public:
+  ASTContext* Ctx;
+  const Preprocessor &PP;
+  const std::string OutDir;
+  AnalyzerOptions Opts;
+  bool declDisplayed;
+
+
+  // PD is owned by AnalysisManager.
+  PathDiagnosticClient *PD;
+
+  StoreManagerCreator CreateStoreMgr;
+  ConstraintManagerCreator CreateConstraintMgr;
+
+  llvm::OwningPtr<AnalysisManager> Mgr;
+
+  AnalysisConsumer(const Preprocessor& pp,
+                   const std::string& outdir,
+                   const AnalyzerOptions& opts)
+    : Ctx(0), PP(pp), OutDir(outdir),
+      Opts(opts), declDisplayed(false), PD(0) {
+    DigestAnalyzerOptions();
+  }
+
+  void DigestAnalyzerOptions() {
+    // Create the PathDiagnosticClient.
+    if (!OutDir.empty()) {
+      switch (Opts.AnalysisDiagOpt) {
+      default:
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
+        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
+#include "clang/Frontend/Analyses.def"
+      }
+    }
+
+    // Create the analyzer component creators.
+    if (ManagerRegistry::StoreMgrCreator != 0) {
+      CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
+    }
+    else {
+      switch (Opts.AnalysisStoreOpt) {
+      default:
+        assert(0 && "Unknown store manager.");
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
+        case NAME##Model: CreateStoreMgr = CREATEFN; break;
+#include "clang/Frontend/Analyses.def"
+      }
+    }
+
+    if (ManagerRegistry::ConstraintMgrCreator != 0)
+      CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
+    else {
+      switch (Opts.AnalysisConstraintsOpt) {
+      default:
+        assert(0 && "Unknown store manager.");
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
+        case NAME##Model: CreateConstraintMgr = CREATEFN; break;
+#include "clang/Frontend/Analyses.def"
+      }
+    }
+  }
+  
+  void DisplayFunction(const Decl *D) {
+    if (!Opts.AnalyzerDisplayProgress || declDisplayed)
+      return;
+      
+    declDisplayed = true;
+    SourceManager &SM = Mgr->getASTContext().getSourceManager();
+    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
+    llvm::errs() << "ANALYZE: " << Loc.getFilename();
+
+    if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+      const NamedDecl *ND = cast<NamedDecl>(D);
+      llvm::errs() << ' ' << ND->getNameAsString() << '\n';
+    }
+    else if (isa<BlockDecl>(D)) {
+      llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
+                   << Loc.getColumn() << '\n';
+    }
+  }
+
+  void addCodeAction(CodeAction action) {
+    FunctionActions.push_back(action);
+    ObjCMethodActions.push_back(action);
+  }
+
+  void addObjCImplementationAction(CodeAction action) {
+    ObjCImplementationActions.push_back(action);
+  }
+
+  void addTranslationUnitAction(CodeAction action) {
+    TranslationUnitActions.push_back(action);
+  }
+
+  virtual void Initialize(ASTContext &Context) {
+    Ctx = &Context;
+    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
+                                  PP.getLangOptions(), PD,
+                                  CreateStoreMgr, CreateConstraintMgr,
+                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
+                                  Opts.PurgeDead, Opts.EagerlyAssume,
+                                  Opts.TrimGraph));
+  }
+
+  virtual void HandleTopLevelDecl(DeclGroupRef D) {
+    declDisplayed = false;
+    for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+      HandleTopLevelSingleDecl(*I);
+  }
+
+  void HandleTopLevelSingleDecl(Decl *D);
+  virtual void HandleTranslationUnit(ASTContext &C);
+
+  void HandleCode(Decl* D, Stmt* Body, Actions& actions);
+};
+} // end anonymous namespace
+
+namespace llvm {
+  template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> {
+    static inline void Profile(AnalysisConsumer::CodeAction X, 
+                               FoldingSetNodeID& ID) {
+      ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
+    }
+  };
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer implementation.
+//===----------------------------------------------------------------------===//
+
+void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
+  switch (D->getKind()) {
+  case Decl::Function: {
+    FunctionDecl* FD = cast<FunctionDecl>(D);
+
+    if (!Opts.AnalyzeSpecificFunction.empty() &&
+        Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
+      break;
+
+    Stmt* Body = FD->getBody();
+    if (Body) HandleCode(FD, Body, FunctionActions);
+    break;
+  }
+
+  case Decl::ObjCMethod: {
+    ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
+
+    if (Opts.AnalyzeSpecificFunction.size() > 0 &&
+        Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
+      return;
+
+    Stmt* Body = MD->getBody();
+    if (Body) HandleCode(MD, Body, ObjCMethodActions);
+    break;
+  }
+
+  case Decl::CXXConstructor:
+  case Decl::CXXDestructor:
+  case Decl::CXXConversion:
+  case Decl::CXXMethod: {
+    CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D);
+
+    if (Opts.AnalyzeSpecificFunction.size() > 0 &&
+        Opts.AnalyzeSpecificFunction != CXXMD->getName())
+      return;
+
+    Stmt *Body = CXXMD->getBody();
+    if (Body) HandleCode(CXXMD, Body, FunctionActions);
+    break;
+  }
+
+  default:
+    break;
+  }
+}
+
+void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
+  
+  TranslationUnitDecl *TU = C.getTranslationUnitDecl();
+  
+  if (!TranslationUnitActions.empty()) {  
+    // Find the entry function definition (if any).
+    FunctionDecl *FD = 0;
+    // Must specify an entry function.
+    if (!Opts.AnalyzeSpecificFunction.empty()) {
+      for (DeclContext::decl_iterator I=TU->decls_begin(), E=TU->decls_end();
+           I != E; ++I) {
+        if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I))
+          if (fd->isThisDeclarationADefinition() &&
+              fd->getNameAsString() == Opts.AnalyzeSpecificFunction) {
+            FD = fd;
+            break;
+          }
+      }
+    }
+
+    if (FD) {
+      for (Actions::iterator I = TranslationUnitActions.begin(), 
+             E = TranslationUnitActions.end(); I != E; ++I)
+        (*I)(*this, *Mgr, FD);  
+    }
+  }
+
+  if (!ObjCImplementationActions.empty()) {
+    for (DeclContext::decl_iterator I = TU->decls_begin(),
+                                    E = TU->decls_end();
+         I != E; ++I)
+      if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
+        HandleCode(ID, 0, ObjCImplementationActions);
+  }
+
+  // Explicitly destroy the PathDiagnosticClient.  This will flush its output.
+  // FIXME: This should be replaced with something that doesn't rely on
+  // side-effects in PathDiagnosticClient's destructor. This is required when
+  // used with option -disable-free.
+  Mgr.reset(NULL);
+}
+
+static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
+  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
+    WL.push_back(BD);
+  
+  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
+       I!=E; ++I)
+    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
+      FindBlocks(DC, WL);
+}
+
+void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
+
+  // Don't run the actions if an error has occured with parsing the file.
+  if (PP.getDiagnostics().hasErrorOccurred())
+    return;
+
+  // Don't run the actions on declarations in header files unless
+  // otherwise specified.
+  if (!Opts.AnalyzeAll &&
+      !Ctx->getSourceManager().isFromMainFile(D->getLocation()))
+    return;
+
+  // Clear the AnalysisManager of old AnalysisContexts.
+  Mgr->ClearContexts();
+  
+  // Dispatch on the actions.
+  llvm::SmallVector<Decl*, 10> WL;
+  WL.push_back(D);
+  
+  if (Body && Opts.AnalyzeNestedBlocks)
+    FindBlocks(cast<DeclContext>(D), WL);
+  
+  for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
+    for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
+         WI != WE; ++WI)
+      (*I)(*this, *Mgr, *WI);
+}
+
+//===----------------------------------------------------------------------===//
+// Analyses
+//===----------------------------------------------------------------------===//
+
+static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
+                                 Decl *D) {
+  if (LiveVariables *L = mgr.getLiveVariables(D)) {
+    C.DisplayFunction(D);
+    BugReporter BR(mgr);
+    CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
+  }
+}
+
+static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
+                                 Decl *D) {
+  if (CFG* c = mgr.getCFG(D)) {
+    C.DisplayFunction(D);
+    CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
+  }
+}
+
+
+static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
+                               Decl *D, 
+                               GRTransferFuncs* tf) {
+
+  llvm::OwningPtr<GRTransferFuncs> TF(tf);
+
+  // Display progress.
+  C.DisplayFunction(D);
+
+  // Construct the analysis engine.  We first query for the LiveVariables
+  // information to see if the CFG is valid.
+  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
+  if (!mgr.getLiveVariables(D))
+    return;  
+  
+  GRExprEngine Eng(mgr, TF.take());
+  
+  if (C.Opts.EnableExperimentalInternalChecks)
+    RegisterExperimentalInternalChecks(Eng);
+  
+  RegisterAppleChecks(Eng, *D);
+  
+  if (C.Opts.EnableExperimentalChecks)
+    RegisterExperimentalChecks(Eng);
+  
+  // Set the graph auditor.
+  llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
+  if (mgr.shouldVisualizeUbigraph()) {
+    Auditor.reset(CreateUbiViz());
+    ExplodedNode::SetAuditor(Auditor.get());
+  }
+
+  // Execute the worklist algorithm.
+  Eng.ExecuteWorkList(mgr.getStackFrame(D));
+
+  // Release the auditor (if any) so that it doesn't monitor the graph
+  // created BugReporter.
+  ExplodedNode::SetAuditor(0);
+
+  // Visualize the exploded graph.
+  if (mgr.shouldVisualizeGraphviz())
+    Eng.ViewGraph(mgr.shouldTrimGraph());
+
+  // Display warnings.
+  Eng.getBugReporter().FlushReports();
+}
+
+static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
+                                  Decl *D, bool GCEnabled) {
+
+  GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
+                                         GCEnabled,
+                                         mgr.getLangOptions());
+
+  ActionGRExprEngine(C, mgr, D, TF);
+}
+
+static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
+                               Decl *D) {
+
+ switch (mgr.getLangOptions().getGCMode()) {
+ default:
+   assert (false && "Invalid GC mode.");
+ case LangOptions::NonGC:
+   ActionObjCMemCheckerAux(C, mgr, D, false);
+   break;
+
+ case LangOptions::GCOnly:
+   ActionObjCMemCheckerAux(C, mgr, D, true);
+   break;
+
+ case LangOptions::HybridGC:
+   ActionObjCMemCheckerAux(C, mgr, D, false);
+   ActionObjCMemCheckerAux(C, mgr, D, true);
+   break;
+ }
+}
+
+static void ActionDisplayLiveVariables(AnalysisConsumer &C,
+                                       AnalysisManager& mgr, Decl *D) {
+  if (LiveVariables* L = mgr.getLiveVariables(D)) {
+    C.DisplayFunction(D);
+    L->dumpBlockLiveness(mgr.getSourceManager());
+  }
+}
+
+static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
+  if (CFG *cfg = mgr.getCFG(D)) {
+    C.DisplayFunction(D);
+    cfg->dump(mgr.getLangOptions());
+  }
+}
+
+static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
+  if (CFG *cfg = mgr.getCFG(D)) {
+    C.DisplayFunction(D);
+    cfg->viewCFG(mgr.getLangOptions());
+  }
+}
+
+static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
+                                          AnalysisManager &mgr, Decl *D) {
+  C.DisplayFunction(D);
+  BugReporter BR(mgr);
+  CheckSecuritySyntaxOnly(D, BR);
+}
+
+static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
+                                  Decl *D) {
+  if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
+    return;
+
+  C.DisplayFunction(D);
+  BugReporter BR(mgr);
+  CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
+}
+
+static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
+                                      Decl *D) {
+  C.DisplayFunction(D);
+  BugReporter BR(mgr);
+  CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
+}
+
+static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
+                                   Decl *D) {
+  C.DisplayFunction(D);
+  BugReporter BR(mgr);
+  CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
+}
+
+static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
+                                    Decl *D) {
+  C.DisplayFunction(D);
+  BugReporter BR(mgr);
+  CheckSizeofPointer(D, BR);
+}
+
+static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
+                             Decl *D) {
+  // FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup.  
+  // Display progress.
+  C.DisplayFunction(D);
+
+  // FIXME: Make a fake transfer function. The GRTransferFunc interface
+  // eventually will be removed.
+  GRExprEngine Eng(mgr, new GRTransferFuncs());
+
+  if (C.Opts.EnableExperimentalInternalChecks)
+    RegisterExperimentalInternalChecks(Eng);
+  
+  RegisterAppleChecks(Eng, *D);
+  
+  if (C.Opts.EnableExperimentalChecks)
+    RegisterExperimentalChecks(Eng);
+
+  // Register call inliner as the last checker.
+  RegisterCallInliner(Eng);
+
+  // Execute the worklist algorithm.
+  Eng.ExecuteWorkList(mgr.getStackFrame(D));
+
+  // Visualize the exploded graph.
+  if (mgr.shouldVisualizeGraphviz())
+    Eng.ViewGraph(mgr.shouldTrimGraph());
+
+  // Display warnings.
+  Eng.getBugReporter().FlushReports();
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer creation.
+//===----------------------------------------------------------------------===//
+
+ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
+                                           const std::string& OutDir,
+                                           const AnalyzerOptions& Opts) {
+  llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
+
+  for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
+    switch (Opts.AnalysisList[i]) {
+#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
+    case NAME:\
+      C->add ## SCOPE ## Action(&Action ## NAME);\
+      break;
+#include "clang/Frontend/Analyses.def"
+    default: break;
+    }
+
+  // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
+  pp.getDiagnostics().setWarningsAsErrors(false);
+
+  return C.take();
+}
+
+//===----------------------------------------------------------------------===//
+// Ubigraph Visualization.  FIXME: Move to separate file.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class UbigraphViz : public ExplodedNode::Auditor {
+  llvm::OwningPtr<llvm::raw_ostream> Out;
+  llvm::sys::Path Dir, Filename;
+  unsigned Cntr;
+
+  typedef llvm::DenseMap<void*,unsigned> VMap;
+  VMap M;
+
+public:
+  UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
+              llvm::sys::Path& filename);
+
+  ~UbigraphViz();
+
+  virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst);
+};
+
+} // end anonymous namespace
+
+static ExplodedNode::Auditor* CreateUbiViz() {
+  std::string ErrMsg;
+
+  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
+  if (!ErrMsg.empty())
+    return 0;
+
+  llvm::sys::Path Filename = Dir;
+  Filename.appendComponent("llvm_ubi");
+  Filename.makeUnique(true,&ErrMsg);
+
+  if (!ErrMsg.empty())
+    return 0;
+
+  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
+
+  llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
+  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
+
+  if (!ErrMsg.empty())
+    return 0;
+
+  return new UbigraphViz(Stream.take(), Dir, Filename);
+}
+
+void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) {
+
+  assert (Src != Dst && "Self-edges are not allowed.");
+
+  // Lookup the Src.  If it is a new node, it's a root.
+  VMap::iterator SrcI= M.find(Src);
+  unsigned SrcID;
+
+  if (SrcI == M.end()) {
+    M[Src] = SrcID = Cntr++;
+    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
+  }
+  else
+    SrcID = SrcI->second;
+
+  // Lookup the Dst.
+  VMap::iterator DstI= M.find(Dst);
+  unsigned DstID;
+
+  if (DstI == M.end()) {
+    M[Dst] = DstID = Cntr++;
+    *Out << "('vertex', " << DstID << ")\n";
+  }
+  else {
+    // We have hit DstID before.  Change its style to reflect a cache hit.
+    DstID = DstI->second;
+    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
+  }
+
+  // Add the edge.
+  *Out << "('edge', " << SrcID << ", " << DstID
+       << ", ('arrow','true'), ('oriented', 'true'))\n";
+}
+
+UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
+                         llvm::sys::Path& filename)
+  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
+
+  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
+  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
+          " ('size', '1.5'))\n";
+}
+
+UbigraphViz::~UbigraphViz() {
+  Out.reset(0);
+  llvm::errs() << "Running 'ubiviz' program... ";
+  std::string ErrMsg;
+  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
+  std::vector<const char*> args;
+  args.push_back(Ubiviz.c_str());
+  args.push_back(Filename.c_str());
+  args.push_back(0);
+
+  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
+    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
+  }
+
+  // Delete the directory.
+  Dir.eraseFromDisk(true);
+}
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp
new file mode 100644
index 0000000..f5291a9
--- /dev/null
+++ b/lib/Frontend/Backend.cpp
@@ -0,0 +1,433 @@
+//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/StandardPasses.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegistry.h"
+using namespace clang;
+using namespace llvm;
+
+namespace {
+  class BackendConsumer : public ASTConsumer {
+    Diagnostic &Diags;
+    BackendAction Action;
+    const CodeGenOptions &CodeGenOpts;
+    const LangOptions &LangOpts;
+    const TargetOptions &TargetOpts;
+    llvm::raw_ostream *AsmOutStream;
+    llvm::formatted_raw_ostream FormattedOutStream;
+    ASTContext *Context;
+
+    Timer LLVMIRGeneration;
+    Timer CodeGenerationTime;
+
+    llvm::OwningPtr<CodeGenerator> Gen;
+
+    llvm::Module *TheModule;
+    llvm::TargetData *TheTargetData;
+
+    mutable FunctionPassManager *CodeGenPasses;
+    mutable PassManager *PerModulePasses;
+    mutable FunctionPassManager *PerFunctionPasses;
+
+    FunctionPassManager *getCodeGenPasses() const;
+    PassManager *getPerModulePasses() const;
+    FunctionPassManager *getPerFunctionPasses() const;
+
+    void CreatePasses();
+
+    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
+    ///
+    /// \return True on success.
+    bool AddEmitPasses();
+
+    void EmitAssembly();
+
+  public:
+    BackendConsumer(BackendAction action, Diagnostic &_Diags,
+                    const LangOptions &langopts, const CodeGenOptions &compopts,
+                    const TargetOptions &targetopts, bool TimePasses,
+                    const std::string &infile, llvm::raw_ostream *OS,
+                    LLVMContext& C) :
+      Diags(_Diags),
+      Action(action),
+      CodeGenOpts(compopts),
+      LangOpts(langopts),
+      TargetOpts(targetopts),
+      AsmOutStream(OS),
+      LLVMIRGeneration("LLVM IR Generation Time"),
+      CodeGenerationTime("Code Generation Time"),
+      Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)),
+      TheModule(0), TheTargetData(0),
+      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {
+
+      if (AsmOutStream)
+        FormattedOutStream.setStream(*AsmOutStream,
+                                     formatted_raw_ostream::PRESERVE_STREAM);
+
+      llvm::TimePassesIsEnabled = TimePasses;
+    }
+
+    ~BackendConsumer() {
+      delete TheTargetData;
+      delete TheModule;
+      delete CodeGenPasses;
+      delete PerModulePasses;
+      delete PerFunctionPasses;
+    }
+
+    virtual void Initialize(ASTContext &Ctx) {
+      Context = &Ctx;
+
+      if (llvm::TimePassesIsEnabled)
+        LLVMIRGeneration.startTimer();
+
+      Gen->Initialize(Ctx);
+
+      TheModule = Gen->GetModule();
+      TheTargetData = new llvm::TargetData(Ctx.Target.getTargetDescription());
+
+      if (llvm::TimePassesIsEnabled)
+        LLVMIRGeneration.stopTimer();
+    }
+
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
+                                     Context->getSourceManager(),
+                                     "LLVM IR generation of declaration");
+
+      if (llvm::TimePassesIsEnabled)
+        LLVMIRGeneration.startTimer();
+
+      Gen->HandleTopLevelDecl(D);
+
+      if (llvm::TimePassesIsEnabled)
+        LLVMIRGeneration.stopTimer();
+    }
+
+    virtual void HandleTranslationUnit(ASTContext &C) {
+      {
+        PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
+        if (llvm::TimePassesIsEnabled)
+          LLVMIRGeneration.startTimer();
+
+        Gen->HandleTranslationUnit(C);
+
+        if (llvm::TimePassesIsEnabled)
+          LLVMIRGeneration.stopTimer();
+      }
+
+      // EmitAssembly times and registers crash info itself.
+      EmitAssembly();
+
+      // Force a flush here in case we never get released.
+      if (AsmOutStream)
+        FormattedOutStream.flush();
+    }
+
+    virtual void HandleTagDeclDefinition(TagDecl *D) {
+      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+                                     Context->getSourceManager(),
+                                     "LLVM IR generation of declaration");
+      Gen->HandleTagDeclDefinition(D);
+    }
+
+    virtual void CompleteTentativeDefinition(VarDecl *D) {
+      Gen->CompleteTentativeDefinition(D);
+    }
+  };
+}
+
+FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
+  if (!CodeGenPasses) {
+    CodeGenPasses = new FunctionPassManager(TheModule);
+    CodeGenPasses->add(new TargetData(*TheTargetData));
+  }
+
+  return CodeGenPasses;
+}
+
+PassManager *BackendConsumer::getPerModulePasses() const {
+  if (!PerModulePasses) {
+    PerModulePasses = new PassManager();
+    PerModulePasses->add(new TargetData(*TheTargetData));
+  }
+
+  return PerModulePasses;
+}
+
+FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
+  if (!PerFunctionPasses) {
+    PerFunctionPasses = new FunctionPassManager(TheModule);
+    PerFunctionPasses->add(new TargetData(*TheTargetData));
+  }
+
+  return PerFunctionPasses;
+}
+
+bool BackendConsumer::AddEmitPasses() {
+  if (Action == Backend_EmitNothing)
+    return true;
+
+  if (Action == Backend_EmitBC) {
+    getPerModulePasses()->add(createBitcodeWriterPass(FormattedOutStream));
+  } else if (Action == Backend_EmitLL) {
+    getPerModulePasses()->add(createPrintModulePass(&FormattedOutStream));
+  } else {
+    bool Fast = CodeGenOpts.OptimizationLevel == 0;
+
+    // Create the TargetMachine for generating code.
+    std::string Error;
+    std::string Triple = TheModule->getTargetTriple();
+    const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
+    if (!TheTarget) {
+      Diags.Report(diag::err_fe_unable_to_create_target) << Error;
+      return false;
+    }
+
+    // FIXME: Expose these capabilities via actual APIs!!!! Aside from just
+    // being gross, this is also totally broken if we ever care about
+    // concurrency.
+    llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim;
+    if (CodeGenOpts.FloatABI == "soft")
+      llvm::FloatABIType = llvm::FloatABI::Soft;
+    else if (CodeGenOpts.FloatABI == "hard")
+      llvm::FloatABIType = llvm::FloatABI::Hard;
+    else {
+      assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
+      llvm::FloatABIType = llvm::FloatABI::Default;
+    }
+    NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
+    llvm::UseSoftFloat = CodeGenOpts.SoftFloat;
+    UnwindTablesMandatory = CodeGenOpts.UnwindTables;
+
+    TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose);
+
+    // FIXME: Parse this earlier.
+    if (CodeGenOpts.RelocationModel == "static") {
+      TargetMachine::setRelocationModel(llvm::Reloc::Static);
+    } else if (CodeGenOpts.RelocationModel == "pic") {
+      TargetMachine::setRelocationModel(llvm::Reloc::PIC_);
+    } else {
+      assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" &&
+             "Invalid PIC model!");
+      TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC);
+    }
+    // FIXME: Parse this earlier.
+    if (CodeGenOpts.CodeModel == "small") {
+      TargetMachine::setCodeModel(llvm::CodeModel::Small);
+    } else if (CodeGenOpts.CodeModel == "kernel") {
+      TargetMachine::setCodeModel(llvm::CodeModel::Kernel);
+    } else if (CodeGenOpts.CodeModel == "medium") {
+      TargetMachine::setCodeModel(llvm::CodeModel::Medium);
+    } else if (CodeGenOpts.CodeModel == "large") {
+      TargetMachine::setCodeModel(llvm::CodeModel::Large);
+    } else {
+      assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
+      TargetMachine::setCodeModel(llvm::CodeModel::Default);
+    }
+
+    std::vector<const char *> BackendArgs;
+    BackendArgs.push_back("clang"); // Fake program name.
+    if (!CodeGenOpts.DebugPass.empty()) {
+      BackendArgs.push_back("-debug-pass");
+      BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
+    }
+    if (!CodeGenOpts.LimitFloatPrecision.empty()) {
+      BackendArgs.push_back("-limit-float-precision");
+      BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
+    }
+    if (llvm::TimePassesIsEnabled)
+      BackendArgs.push_back("-time-passes");
+    BackendArgs.push_back(0);
+    llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
+                                      (char**) &BackendArgs[0]);
+
+    std::string FeaturesStr;
+    if (TargetOpts.CPU.size() || TargetOpts.Features.size()) {
+      SubtargetFeatures Features;
+      Features.setCPU(TargetOpts.CPU);
+      for (std::vector<std::string>::const_iterator
+             it = TargetOpts.Features.begin(),
+             ie = TargetOpts.Features.end(); it != ie; ++it)
+        Features.AddFeature(*it);
+      FeaturesStr = Features.getString();
+    }
+    TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr);
+
+    // Set register scheduler & allocation policy.
+    RegisterScheduler::setDefault(createDefaultScheduler);
+    RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
+                                 createLinearScanRegisterAllocator);
+
+    // From llvm-gcc:
+    // If there are passes we have to run on the entire module, we do codegen
+    // as a separate "pass" after that happens.
+    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
+    // this for fast -O0 compiles!
+    FunctionPassManager *PM = getCodeGenPasses();
+    CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
+
+    switch (CodeGenOpts.OptimizationLevel) {
+    default: break;
+    case 0: OptLevel = CodeGenOpt::None; break;
+    case 3: OptLevel = CodeGenOpt::Aggressive; break;
+    }
+
+    // Normal mode, emit a .s or .o file by running the code generator. Note,
+    // this also adds codegenerator level optimization passes.
+    TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile;
+    if (Action == Backend_EmitObj)
+      CGFT = TargetMachine::CGFT_ObjectFile;
+    if (TM->addPassesToEmitFile(*PM, FormattedOutStream, CGFT, OptLevel)) {
+      Diags.Report(diag::err_fe_unable_to_interface_with_target);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void BackendConsumer::CreatePasses() {
+  unsigned OptLevel = CodeGenOpts.OptimizationLevel;
+  CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining;
+
+  // Handle disabling of LLVM optimization, where we want to preserve the
+  // internal module before any optimization.
+  if (CodeGenOpts.DisableLLVMOpts) {
+    OptLevel = 0;
+    Inlining = CodeGenOpts.NoInlining;
+  }
+
+  // In -O0 if checking is disabled, we don't even have per-function passes.
+  if (CodeGenOpts.VerifyModule)
+    getPerFunctionPasses()->add(createVerifierPass());
+
+  // Assume that standard function passes aren't run for -O0.
+  if (OptLevel > 0)
+    llvm::createStandardFunctionPasses(getPerFunctionPasses(), OptLevel);
+
+  llvm::Pass *InliningPass = 0;
+  switch (Inlining) {
+  case CodeGenOptions::NoInlining: break;
+  case CodeGenOptions::NormalInlining: {
+    // Set the inline threshold following llvm-gcc.
+    //
+    // FIXME: Derive these constants in a principled fashion.
+    unsigned Threshold = 225;
+    if (CodeGenOpts.OptimizeSize)
+      Threshold = 75;
+    else if (OptLevel > 2)
+      Threshold = 275;
+    InliningPass = createFunctionInliningPass(Threshold);
+    break;
+  }
+  case CodeGenOptions::OnlyAlwaysInlining:
+    InliningPass = createAlwaysInlinerPass();         // Respect always_inline
+    break;
+  }
+
+  // For now we always create per module passes.
+  PassManager *PM = getPerModulePasses();
+  llvm::createStandardModulePasses(PM, OptLevel, CodeGenOpts.OptimizeSize,
+                                   CodeGenOpts.UnitAtATime,
+                                   CodeGenOpts.UnrollLoops,
+                                   /*SimplifyLibCalls=*/!LangOpts.NoBuiltin,
+                                   /*HaveExceptions=*/true,
+                                   InliningPass);
+}
+
+/// EmitAssembly - Handle interaction with LLVM backend to generate
+/// actual machine code.
+void BackendConsumer::EmitAssembly() {
+  // Silently ignore if we weren't initialized for some reason.
+  if (!TheModule || !TheTargetData)
+    return;
+
+  TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0);
+
+  // Make sure IR generation is happy with the module. This is
+  // released by the module provider.
+  Module *M = Gen->ReleaseModule();
+  if (!M) {
+    // The module has been released by IR gen on failures, do not
+    // double free.
+    TheModule = 0;
+    return;
+  }
+
+  assert(TheModule == M && "Unexpected module change during IR generation");
+
+  CreatePasses();
+  if (!AddEmitPasses())
+    return;
+
+  // Run passes. For now we do all passes at once, but eventually we
+  // would like to have the option of streaming code generation.
+
+  if (PerFunctionPasses) {
+    PrettyStackTraceString CrashInfo("Per-function optimization");
+
+    PerFunctionPasses->doInitialization();
+    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+      if (!I->isDeclaration())
+        PerFunctionPasses->run(*I);
+    PerFunctionPasses->doFinalization();
+  }
+
+  if (PerModulePasses) {
+    PrettyStackTraceString CrashInfo("Per-module optimization passes");
+    PerModulePasses->run(*M);
+  }
+
+  if (CodeGenPasses) {
+    PrettyStackTraceString CrashInfo("Code generation");
+    CodeGenPasses->doInitialization();
+    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+      if (!I->isDeclaration())
+        CodeGenPasses->run(*I);
+    CodeGenPasses->doFinalization();
+  }
+}
+
+ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
+                                          Diagnostic &Diags,
+                                          const LangOptions &LangOpts,
+                                          const CodeGenOptions &CodeGenOpts,
+                                          const TargetOptions &TargetOpts,
+                                          bool TimePasses,
+                                          const std::string& InFile,
+                                          llvm::raw_ostream* OS,
+                                          LLVMContext& C) {
+  return new BackendConsumer(Action, Diags, LangOpts, CodeGenOpts,
+                             TargetOpts, TimePasses, InFile, OS, C);
+}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
new file mode 100644
index 0000000..1d0b5c1
--- /dev/null
+++ b/lib/Frontend/CMakeLists.txt
@@ -0,0 +1,57 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangFrontend
+  ASTConsumers.cpp
+  ASTMerge.cpp
+  ASTUnit.cpp
+  AnalysisConsumer.cpp
+  Backend.cpp
+  CacheTokens.cpp
+  CompilerInstance.cpp
+  CompilerInvocation.cpp
+  DeclXML.cpp
+  DependencyFile.cpp
+  DiagChecker.cpp
+  DocumentXML.cpp
+  FixItRewriter.cpp
+  FrontendAction.cpp
+  FrontendActions.cpp
+  FrontendOptions.cpp
+  GeneratePCH.cpp
+  HTMLDiagnostics.cpp
+  HTMLPrint.cpp
+  InitHeaderSearch.cpp
+  InitPreprocessor.cpp
+  LangStandards.cpp
+  PCHReader.cpp
+  PCHReaderDecl.cpp
+  PCHReaderStmt.cpp
+  PCHWriter.cpp
+  PCHWriterDecl.cpp
+  PCHWriterStmt.cpp
+  PlistDiagnostics.cpp
+  PrintParserCallbacks.cpp
+  PrintPreprocessedOutput.cpp
+  RewriteMacros.cpp
+  RewriteObjC.cpp
+  RewriteTest.cpp
+  StmtXML.cpp
+  TextDiagnosticBuffer.cpp
+  TextDiagnosticPrinter.cpp
+  TypeXML.cpp
+  VerifyDiagnosticsClient.cpp
+  Warnings.cpp
+  )
+
+IF(MSVC)
+  get_target_property(NON_ANSI_COMPILE_FLAGS clangFrontend COMPILE_FLAGS)
+  string(REPLACE /Za
+    "" NON_ANSI_COMPILE_FLAGS
+    ${NON_ANSI_COMPILE_FLAGS})
+  set_target_properties(clangFrontend PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+ENDIF(MSVC)
+
+add_dependencies(clangFrontend 
+  ClangDiagnosticFrontend 
+  ClangDiagnosticLex
+  ClangDiagnosticSema)
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
new file mode 100644
index 0000000..7326937
--- /dev/null
+++ b/lib/Frontend/CacheTokens.cpp
@@ -0,0 +1,659 @@
+//===--- CacheTokens.cpp - Caching of lexer tokens for PTH support --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides a possible implementation of PTH support for Clang that is
+// based on caching lexed tokens and identifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+
+// FIXME: put this somewhere else?
+#ifndef S_ISDIR
+#define S_ISDIR(x) (((x)&_S_IFDIR)!=0)
+#endif
+
+using namespace clang;
+using namespace clang::io;
+
+//===----------------------------------------------------------------------===//
+// PTH-specific stuff.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PTHEntry {
+  Offset TokenData, PPCondData;
+
+public:
+  PTHEntry() {}
+
+  PTHEntry(Offset td, Offset ppcd)
+    : TokenData(td), PPCondData(ppcd) {}
+
+  Offset getTokenOffset() const { return TokenData; }
+  Offset getPPCondTableOffset() const { return PPCondData; }
+};
+
+
+class PTHEntryKeyVariant {
+  union { const FileEntry* FE; const char* Path; };
+  enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind;
+  struct stat *StatBuf;
+public:
+  PTHEntryKeyVariant(const FileEntry *fe)
+    : FE(fe), Kind(IsFE), StatBuf(0) {}
+
+  PTHEntryKeyVariant(struct stat* statbuf, const char* path)
+    : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {}
+
+  PTHEntryKeyVariant(const char* path)
+    : Path(path), Kind(IsNoExist), StatBuf(0) {}
+
+  bool isFile() const { return Kind == IsFE; }
+
+  llvm::StringRef getString() const {
+    return Kind == IsFE ? FE->getName() : Path;
+  }
+
+  unsigned getKind() const { return (unsigned) Kind; }
+
+  void EmitData(llvm::raw_ostream& Out) {
+    switch (Kind) {
+    case IsFE:
+      // Emit stat information.
+      ::Emit32(Out, FE->getInode());
+      ::Emit32(Out, FE->getDevice());
+      ::Emit16(Out, FE->getFileMode());
+      ::Emit64(Out, FE->getModificationTime());
+      ::Emit64(Out, FE->getSize());
+      break;
+    case IsDE:
+      // Emit stat information.
+      ::Emit32(Out, (uint32_t) StatBuf->st_ino);
+      ::Emit32(Out, (uint32_t) StatBuf->st_dev);
+      ::Emit16(Out, (uint16_t) StatBuf->st_mode);
+      ::Emit64(Out, (uint64_t) StatBuf->st_mtime);
+      ::Emit64(Out, (uint64_t) StatBuf->st_size);
+      delete StatBuf;
+      break;
+    default:
+      break;
+    }
+  }
+
+  unsigned getRepresentationLength() const {
+    return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8;
+  }
+};
+
+class FileEntryPTHEntryInfo {
+public:
+  typedef PTHEntryKeyVariant key_type;
+  typedef key_type key_type_ref;
+
+  typedef PTHEntry data_type;
+  typedef const PTHEntry& data_type_ref;
+
+  static unsigned ComputeHash(PTHEntryKeyVariant V) {
+    return llvm::HashString(V.getString());
+  }
+
+  static std::pair<unsigned,unsigned>
+  EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
+                    const PTHEntry& E) {
+
+    unsigned n = V.getString().size() + 1 + 1;
+    ::Emit16(Out, n);
+
+    unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
+    ::Emit8(Out, m);
+
+    return std::make_pair(n, m);
+  }
+
+  static void EmitKey(llvm::raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){
+    // Emit the entry kind.
+    ::Emit8(Out, (unsigned) V.getKind());
+    // Emit the string.
+    Out.write(V.getString().data(), n - 1);
+  }
+
+  static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
+                       const PTHEntry& E, unsigned) {
+
+
+    // For file entries emit the offsets into the PTH file for token data
+    // and the preprocessor blocks table.
+    if (V.isFile()) {
+      ::Emit32(Out, E.getTokenOffset());
+      ::Emit32(Out, E.getPPCondTableOffset());
+    }
+
+    // Emit any other data associated with the key (i.e., stat information).
+    V.EmitData(Out);
+  }
+};
+
+class OffsetOpt {
+  bool valid;
+  Offset off;
+public:
+  OffsetOpt() : valid(false) {}
+  bool hasOffset() const { return valid; }
+  Offset getOffset() const { assert(valid); return off; }
+  void setOffset(Offset o) { off = o; valid = true; }
+};
+} // end anonymous namespace
+
+typedef OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap;
+typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;
+typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
+
+namespace {
+class PTHWriter {
+  IDMap IM;
+  llvm::raw_fd_ostream& Out;
+  Preprocessor& PP;
+  uint32_t idcount;
+  PTHMap PM;
+  CachedStrsTy CachedStrs;
+  Offset CurStrOffset;
+  std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries;
+
+  //// Get the persistent id for the given IdentifierInfo*.
+  uint32_t ResolveID(const IdentifierInfo* II);
+
+  /// Emit a token to the PTH file.
+  void EmitToken(const Token& T);
+
+  void Emit8(uint32_t V) {
+    Out << (unsigned char)(V);
+  }
+
+  void Emit16(uint32_t V) { ::Emit16(Out, V); }
+
+  void Emit24(uint32_t V) {
+    Out << (unsigned char)(V);
+    Out << (unsigned char)(V >>  8);
+    Out << (unsigned char)(V >> 16);
+    assert((V >> 24) == 0);
+  }
+
+  void Emit32(uint32_t V) { ::Emit32(Out, V); }
+
+  void EmitBuf(const char *Ptr, unsigned NumBytes) {
+    Out.write(Ptr, NumBytes);
+  }
+
+  /// EmitIdentifierTable - Emits two tables to the PTH file.  The first is
+  ///  a hashtable mapping from identifier strings to persistent IDs.
+  ///  The second is a straight table mapping from persistent IDs to string data
+  ///  (the keys of the first table).
+  std::pair<Offset, Offset> EmitIdentifierTable();
+
+  /// EmitFileTable - Emit a table mapping from file name strings to PTH
+  /// token data.
+  Offset EmitFileTable() { return PM.Emit(Out); }
+
+  PTHEntry LexTokens(Lexer& L);
+  Offset EmitCachedSpellings();
+
+public:
+  PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
+    : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
+
+  PTHMap &getPM() { return PM; }
+  void GeneratePTH(const std::string *MainFile = 0);
+};
+} // end anonymous namespace
+
+uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
+  // Null IdentifierInfo's map to the persistent ID 0.
+  if (!II)
+    return 0;
+
+  IDMap::iterator I = IM.find(II);
+  if (I != IM.end())
+    return I->second; // We've already added 1.
+
+  IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL.
+  return idcount;
+}
+
+void PTHWriter::EmitToken(const Token& T) {
+  // Emit the token kind, flags, and length.
+  Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)|
+         (((uint32_t) T.getLength()) << 16));
+
+  if (!T.isLiteral()) {
+    Emit32(ResolveID(T.getIdentifierInfo()));
+  } else {
+    // We cache *un-cleaned* spellings. This gives us 100% fidelity with the
+    // source code.
+    const char* s = T.getLiteralData();
+    unsigned len = T.getLength();
+
+    // Get the string entry.
+    llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len);
+
+    // If this is a new string entry, bump the PTH offset.
+    if (!E->getValue().hasOffset()) {
+      E->getValue().setOffset(CurStrOffset);
+      StrEntries.push_back(E);
+      CurStrOffset += len + 1;
+    }
+
+    // Emit the relative offset into the PTH file for the spelling string.
+    Emit32(E->getValue().getOffset());
+  }
+
+  // Emit the offset into the original source file of this token so that we
+  // can reconstruct its SourceLocation.
+  Emit32(PP.getSourceManager().getFileOffset(T.getLocation()));
+}
+
+PTHEntry PTHWriter::LexTokens(Lexer& L) {
+  // Pad 0's so that we emit tokens to a 4-byte alignment.
+  // This speed up reading them back in.
+  Pad(Out, 4);
+  Offset off = (Offset) Out.tell();
+
+  // Keep track of matching '#if' ... '#endif'.
+  typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
+  PPCondTable PPCond;
+  std::vector<unsigned> PPStartCond;
+  bool ParsingPreprocessorDirective = false;
+  Token Tok;
+
+  do {
+    L.LexFromRawLexer(Tok);
+  NextToken:
+
+    if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
+        ParsingPreprocessorDirective) {
+      // Insert an eom token into the token cache.  It has the same
+      // position as the next token that is not on the same line as the
+      // preprocessor directive.  Observe that we continue processing
+      // 'Tok' when we exit this branch.
+      Token Tmp = Tok;
+      Tmp.setKind(tok::eom);
+      Tmp.clearFlag(Token::StartOfLine);
+      Tmp.setIdentifierInfo(0);
+      EmitToken(Tmp);
+      ParsingPreprocessorDirective = false;
+    }
+
+    if (Tok.is(tok::identifier)) {
+      Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
+      EmitToken(Tok);
+      continue;
+    }
+
+    if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
+      // Special processing for #include.  Store the '#' token and lex
+      // the next token.
+      assert(!ParsingPreprocessorDirective);
+      Offset HashOff = (Offset) Out.tell();
+      EmitToken(Tok);
+
+      // Get the next token.
+      L.LexFromRawLexer(Tok);
+
+      // If we see the start of line, then we had a null directive "#".
+      if (Tok.isAtStartOfLine())
+        goto NextToken;
+
+      // Did we see 'include'/'import'/'include_next'?
+      if (Tok.isNot(tok::identifier)) {
+        EmitToken(Tok);
+        continue;
+      }
+
+      IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
+      Tok.setIdentifierInfo(II);
+      tok::PPKeywordKind K = II->getPPKeywordID();
+
+      ParsingPreprocessorDirective = true;
+
+      switch (K) {
+      case tok::pp_not_keyword:
+        // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass
+        // them through.
+      default:
+        break;
+
+      case tok::pp_include:
+      case tok::pp_import:
+      case tok::pp_include_next: {
+        // Save the 'include' token.
+        EmitToken(Tok);
+        // Lex the next token as an include string.
+        L.setParsingPreprocessorDirective(true);
+        L.LexIncludeFilename(Tok);
+        L.setParsingPreprocessorDirective(false);
+        assert(!Tok.isAtStartOfLine());
+        if (Tok.is(tok::identifier))
+          Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
+
+        break;
+      }
+      case tok::pp_if:
+      case tok::pp_ifdef:
+      case tok::pp_ifndef: {
+        // Add an entry for '#if' and friends.  We initially set the target
+        // index to 0.  This will get backpatched when we hit #endif.
+        PPStartCond.push_back(PPCond.size());
+        PPCond.push_back(std::make_pair(HashOff, 0U));
+        break;
+      }
+      case tok::pp_endif: {
+        // Add an entry for '#endif'.  We set the target table index to itself.
+        // This will later be set to zero when emitting to the PTH file.  We
+        // use 0 for uninitialized indices because that is easier to debug.
+        unsigned index = PPCond.size();
+        // Backpatch the opening '#if' entry.
+        assert(!PPStartCond.empty());
+        assert(PPCond.size() > PPStartCond.back());
+        assert(PPCond[PPStartCond.back()].second == 0);
+        PPCond[PPStartCond.back()].second = index;
+        PPStartCond.pop_back();
+        // Add the new entry to PPCond.
+        PPCond.push_back(std::make_pair(HashOff, index));
+        EmitToken(Tok);
+
+        // Some files have gibberish on the same line as '#endif'.
+        // Discard these tokens.
+        do
+          L.LexFromRawLexer(Tok);
+        while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine());
+        // We have the next token in hand.
+        // Don't immediately lex the next one.
+        goto NextToken;
+      }
+      case tok::pp_elif:
+      case tok::pp_else: {
+        // Add an entry for #elif or #else.
+        // This serves as both a closing and opening of a conditional block.
+        // This means that its entry will get backpatched later.
+        unsigned index = PPCond.size();
+        // Backpatch the previous '#if' entry.
+        assert(!PPStartCond.empty());
+        assert(PPCond.size() > PPStartCond.back());
+        assert(PPCond[PPStartCond.back()].second == 0);
+        PPCond[PPStartCond.back()].second = index;
+        PPStartCond.pop_back();
+        // Now add '#elif' as a new block opening.
+        PPCond.push_back(std::make_pair(HashOff, 0U));
+        PPStartCond.push_back(index);
+        break;
+      }
+      }
+    }
+
+    EmitToken(Tok);
+  }
+  while (Tok.isNot(tok::eof));
+
+  assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");
+
+  // Next write out PPCond.
+  Offset PPCondOff = (Offset) Out.tell();
+
+  // Write out the size of PPCond so that clients can identifer empty tables.
+  Emit32(PPCond.size());
+
+  for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
+    Emit32(PPCond[i].first - off);
+    uint32_t x = PPCond[i].second;
+    assert(x != 0 && "PPCond entry not backpatched.");
+    // Emit zero for #endifs.  This allows us to do checking when
+    // we read the PTH file back in.
+    Emit32(x == i ? 0 : x);
+  }
+
+  return PTHEntry(off, PPCondOff);
+}
+
+Offset PTHWriter::EmitCachedSpellings() {
+  // Write each cached strings to the PTH file.
+  Offset SpellingsOff = Out.tell();
+
+  for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator
+       I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I)
+    EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/);
+
+  return SpellingsOff;
+}
+
+void PTHWriter::GeneratePTH(const std::string *MainFile) {
+  // Generate the prologue.
+  Out << "cfe-pth";
+  Emit32(PTHManager::Version);
+
+  // Leave 4 words for the prologue.
+  Offset PrologueOffset = Out.tell();
+  for (unsigned i = 0; i < 4; ++i)
+    Emit32(0);
+
+  // Write the name of the MainFile.
+  if (MainFile && !MainFile->empty()) {
+    Emit16(MainFile->length());
+    EmitBuf(MainFile->data(), MainFile->length());
+  } else {
+    // String with 0 bytes.
+    Emit16(0);
+  }
+  Emit8(0);
+
+  // Iterate over all the files in SourceManager.  Create a lexer
+  // for each file and cache the tokens.
+  SourceManager &SM = PP.getSourceManager();
+  const LangOptions &LOpts = PP.getLangOptions();
+
+  for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
+       E = SM.fileinfo_end(); I != E; ++I) {
+    const SrcMgr::ContentCache &C = *I->second;
+    const FileEntry *FE = C.Entry;
+
+    // FIXME: Handle files with non-absolute paths.
+    llvm::sys::Path P(FE->getName());
+    if (!P.isAbsolute())
+      continue;
+
+    const llvm::MemoryBuffer *B = C.getBuffer();
+    if (!B) continue;
+
+    FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
+    const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+    Lexer L(FID, FromFile, SM, LOpts);
+    PM.insert(FE, LexTokens(L));
+  }
+
+  // Write out the identifier table.
+  const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable();
+
+  // Write out the cached strings table.
+  Offset SpellingOff = EmitCachedSpellings();
+
+  // Write out the file table.
+  Offset FileTableOff = EmitFileTable();
+
+  // Finally, write the prologue.
+  Out.seek(PrologueOffset);
+  Emit32(IdTableOff.first);
+  Emit32(IdTableOff.second);
+  Emit32(FileTableOff);
+  Emit32(SpellingOff);
+}
+
+namespace {
+/// StatListener - A simple "interpose" object used to monitor stat calls
+/// invoked by FileManager while processing the original sources used
+/// as input to PTH generation.  StatListener populates the PTHWriter's
+/// file map with stat information for directories as well as negative stats.
+/// Stat information for files are populated elsewhere.
+class StatListener : public StatSysCallCache {
+  PTHMap &PM;
+public:
+  StatListener(PTHMap &pm) : PM(pm) {}
+  ~StatListener() {}
+
+  int stat(const char *path, struct stat *buf) {
+    int result = StatSysCallCache::stat(path, buf);
+
+    if (result != 0) // Failed 'stat'.
+      PM.insert(path, PTHEntry());
+    else if (S_ISDIR(buf->st_mode)) {
+      // Only cache directories with absolute paths.
+      if (!llvm::sys::Path(path).isAbsolute())
+        return result;
+
+      PM.insert(PTHEntryKeyVariant(buf, path), PTHEntry());
+    }
+
+    return result;
+  }
+};
+} // end anonymous namespace
+
+
+void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
+  // Get the name of the main file.
+  const SourceManager &SrcMgr = PP.getSourceManager();
+  const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
+  llvm::sys::Path MainFilePath(MainFile->getName());
+  std::string MainFileName;
+
+  if (!MainFilePath.isAbsolute()) {
+    llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
+    P.appendComponent(MainFilePath.str());
+    MainFileName = P.str();
+  } else {
+    MainFileName = MainFilePath.str();
+  }
+
+  // Create the PTHWriter.
+  PTHWriter PW(*OS, PP);
+
+  // Install the 'stat' system call listener in the FileManager.
+  StatListener *StatCache = new StatListener(PW.getPM());
+  PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true);
+
+  // Lex through the entire file.  This will populate SourceManager with
+  // all of the header information.
+  Token Tok;
+  PP.EnterMainSourceFile();
+  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
+
+  // Generate the PTH file.
+  PP.getFileManager().removeStatCache(StatCache);
+  PW.GeneratePTH(&MainFileName);
+}
+
+//===----------------------------------------------------------------------===//
+
+class PTHIdKey {
+public:
+  const IdentifierInfo* II;
+  uint32_t FileOffset;
+};
+
+namespace {
+class PTHIdentifierTableTrait {
+public:
+  typedef PTHIdKey* key_type;
+  typedef key_type  key_type_ref;
+
+  typedef uint32_t  data_type;
+  typedef data_type data_type_ref;
+
+  static unsigned ComputeHash(PTHIdKey* key) {
+    return llvm::HashString(key->II->getName());
+  }
+
+  static std::pair<unsigned,unsigned>
+  EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) {
+    unsigned n = key->II->getLength() + 1;
+    ::Emit16(Out, n);
+    return std::make_pair(n, sizeof(uint32_t));
+  }
+
+  static void EmitKey(llvm::raw_ostream& Out, PTHIdKey* key, unsigned n) {
+    // Record the location of the key data.  This is used when generating
+    // the mapping from persistent IDs to strings.
+    key->FileOffset = Out.tell();
+    Out.write(key->II->getNameStart(), n);
+  }
+
+  static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID,
+                       unsigned) {
+    ::Emit32(Out, pID);
+  }
+};
+} // end anonymous namespace
+
+/// EmitIdentifierTable - Emits two tables to the PTH file.  The first is
+///  a hashtable mapping from identifier strings to persistent IDs.  The second
+///  is a straight table mapping from persistent IDs to string data (the
+///  keys of the first table).
+///
+std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
+  // Build two maps:
+  //  (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset)
+  //  (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs
+
+  // Note that we use 'calloc', so all the bytes are 0.
+  PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey));
+
+  // Create the hashtable.
+  OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
+
+  // Generate mapping from persistent IDs -> IdentifierInfo*.
+  for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) {
+    // Decrement by 1 because we are using a vector for the lookup and
+    // 0 is reserved for NULL.
+    assert(I->second > 0);
+    assert(I->second-1 < idcount);
+    unsigned idx = I->second-1;
+
+    // Store the mapping from persistent ID to IdentifierInfo*
+    IIDMap[idx].II = I->first;
+
+    // Store the reverse mapping in a hashtable.
+    IIOffMap.insert(&IIDMap[idx], I->second);
+  }
+
+  // Write out the inverse map first.  This causes the PCIDKey entries to
+  // record PTH file offsets for the string data.  This is used to write
+  // the second table.
+  Offset StringTableOffset = IIOffMap.Emit(Out);
+
+  // Now emit the table mapping from persistent IDs to PTH file offsets.
+  Offset IDOff = Out.tell();
+  Emit32(idcount);  // Emit the number of identifiers.
+  for (unsigned i = 0 ; i < idcount; ++i)
+    Emit32(IIDMap[i].FileOffset);
+
+  // Finally, release the inverse map.
+  free(IIDMap);
+
+  return std::make_pair(IDOff, StringTableOffset);
+}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
new file mode 100644
index 0000000..a630486
--- /dev/null
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -0,0 +1,537 @@
+//===--- CompilerInstance.cpp ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Frontend/ChainedDiagnosticClient.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
+using namespace clang;
+
+CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
+                                   bool _OwnsLLVMContext)
+  : LLVMContext(_LLVMContext),
+    OwnsLLVMContext(_OwnsLLVMContext),
+    Invocation(new CompilerInvocation) {
+}
+
+CompilerInstance::~CompilerInstance() {
+  if (OwnsLLVMContext)
+    delete LLVMContext;
+}
+
+void CompilerInstance::setInvocation(CompilerInvocation *Value) {
+  Invocation.reset(Value);
+}
+
+void CompilerInstance::setDiagnostics(Diagnostic *Value) {
+  Diagnostics.reset(Value);
+}
+
+void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
+  DiagClient.reset(Value);
+}
+
+void CompilerInstance::setTarget(TargetInfo *Value) {
+  Target.reset(Value);
+}
+
+void CompilerInstance::setFileManager(FileManager *Value) {
+  FileMgr.reset(Value);
+}
+
+void CompilerInstance::setSourceManager(SourceManager *Value) {
+  SourceMgr.reset(Value);
+}
+
+void CompilerInstance::setPreprocessor(Preprocessor *Value) {
+  PP.reset(Value);
+}
+
+void CompilerInstance::setASTContext(ASTContext *Value) {
+  Context.reset(Value);
+}
+
+void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
+  Consumer.reset(Value);
+}
+
+void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
+  CompletionConsumer.reset(Value);
+}
+
+// Diagnostics
+namespace {
+  class BinaryDiagnosticSerializer : public DiagnosticClient {
+    llvm::raw_ostream &OS;
+    SourceManager *SourceMgr;
+  public:
+    explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
+      : OS(OS), SourceMgr(0) { }
+    
+    virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                  const DiagnosticInfo &Info);
+  };
+}
+
+void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                                  const DiagnosticInfo &Info) {
+  Info.Serialize(DiagLevel, OS);
+}
+
+static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
+                              unsigned argc, char **argv,
+                              llvm::OwningPtr<DiagnosticClient> &DiagClient) {
+  std::string ErrorInfo;
+  llvm::raw_ostream *OS =
+    new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
+  if (!ErrorInfo.empty()) {
+    // FIXME: Do not fail like this.
+    llvm::errs() << "error opening -dump-build-information file '"
+                 << DiagOpts.DumpBuildInformation << "', option ignored!\n";
+    delete OS;
+    return;
+  }
+
+  (*OS) << "clang -cc1 command line arguments: ";
+  for (unsigned i = 0; i != argc; ++i)
+    (*OS) << argv[i] << ' ';
+  (*OS) << '\n';
+
+  // Chain in a diagnostic client which will log the diagnostics.
+  DiagnosticClient *Logger =
+    new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
+  DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
+}
+
+void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
+  Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
+
+  if (Diagnostics)
+    DiagClient.reset(Diagnostics->getClient());
+}
+
+Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
+                                                int Argc, char **Argv) {
+  llvm::OwningPtr<Diagnostic> Diags(new Diagnostic());
+
+  // Create the diagnostic client for reporting errors or for
+  // implementing -verify.
+  llvm::OwningPtr<DiagnosticClient> DiagClient;
+  if (Opts.BinaryOutput) {
+    if (llvm::sys::Program::ChangeStderrToBinary()) {
+      // We weren't able to set standard error to binary, which is a
+      // bit of a problem. So, just create a text diagnostic printer
+      // to complain about this problem, and pretend that the user
+      // didn't try to use binary output.
+      DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
+      Diags->setClient(DiagClient.take());
+      Diags->Report(diag::err_fe_stderr_binary);
+      return Diags.take();
+    } else {
+      DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
+    }
+  } else {
+    DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
+  }
+
+  // Chain in -verify checker, if requested.
+  if (Opts.VerifyDiagnostics)
+    DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
+
+  if (!Opts.DumpBuildInformation.empty())
+    SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
+
+  // Configure our handling of diagnostics.
+  Diags->setClient(DiagClient.take());
+  if (ProcessWarningOptions(*Diags, Opts))
+    return 0;
+
+  return Diags.take();
+}
+
+// File Manager
+
+void CompilerInstance::createFileManager() {
+  FileMgr.reset(new FileManager());
+}
+
+// Source Manager
+
+void CompilerInstance::createSourceManager() {
+  SourceMgr.reset(new SourceManager());
+}
+
+// Preprocessor
+
+void CompilerInstance::createPreprocessor() {
+  PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
+                              getPreprocessorOpts(), getHeaderSearchOpts(),
+                              getDependencyOutputOpts(), getTarget(),
+                              getFrontendOpts(), getSourceManager(),
+                              getFileManager()));
+}
+
+Preprocessor *
+CompilerInstance::createPreprocessor(Diagnostic &Diags,
+                                     const LangOptions &LangInfo,
+                                     const PreprocessorOptions &PPOpts,
+                                     const HeaderSearchOptions &HSOpts,
+                                     const DependencyOutputOptions &DepOpts,
+                                     const TargetInfo &Target,
+                                     const FrontendOptions &FEOpts,
+                                     SourceManager &SourceMgr,
+                                     FileManager &FileMgr) {
+  // Create a PTH manager if we are using some form of a token cache.
+  PTHManager *PTHMgr = 0;
+  if (!PPOpts.TokenCache.empty())
+    PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
+
+  // Create the Preprocessor.
+  HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
+  Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
+                                      SourceMgr, *HeaderInfo, PTHMgr,
+                                      /*OwnsHeaderSearch=*/true);
+
+  // Note that this is different then passing PTHMgr to Preprocessor's ctor.
+  // That argument is used as the IdentifierInfoLookup argument to
+  // IdentifierTable's ctor.
+  if (PTHMgr) {
+    PTHMgr->setPreprocessor(PP);
+    PP->setPTHManager(PTHMgr);
+  }
+
+  InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
+
+  // Handle generating dependencies, if requested.
+  if (!DepOpts.OutputFile.empty())
+    AttachDependencyFileGen(*PP, DepOpts);
+
+  return PP;
+}
+
+// ASTContext
+
+void CompilerInstance::createASTContext() {
+  Preprocessor &PP = getPreprocessor();
+  Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
+                               getTarget(), PP.getIdentifierTable(),
+                               PP.getSelectorTable(), PP.getBuiltinInfo(),
+                               /*FreeMemory=*/ !getFrontendOpts().DisableFree,
+                               /*size_reserve=*/ 0));
+}
+
+// ExternalASTSource
+
+void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
+  llvm::OwningPtr<ExternalASTSource> Source;
+  Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
+                                          getPreprocessor(), getASTContext()));
+  getASTContext().setExternalSource(Source);
+}
+
+ExternalASTSource *
+CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+                                             const std::string &Sysroot,
+                                             Preprocessor &PP,
+                                             ASTContext &Context) {
+  llvm::OwningPtr<PCHReader> Reader;
+  Reader.reset(new PCHReader(PP, &Context,
+                             Sysroot.empty() ? 0 : Sysroot.c_str()));
+
+  switch (Reader->ReadPCH(Path)) {
+  case PCHReader::Success:
+    // Set the predefines buffer as suggested by the PCH reader. Typically, the
+    // predefines buffer will be empty.
+    PP.setPredefines(Reader->getSuggestedPredefines());
+    return Reader.take();
+
+  case PCHReader::Failure:
+    // Unrecoverable failure: don't even try to process the input file.
+    break;
+
+  case PCHReader::IgnorePCH:
+    // No suitable PCH file could be found. Return an error.
+    break;
+  }
+
+  return 0;
+}
+
+// Code Completion
+
+void CompilerInstance::createCodeCompletionConsumer() {
+  const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
+  CompletionConsumer.reset(
+    createCodeCompletionConsumer(getPreprocessor(),
+                                 Loc.FileName, Loc.Line, Loc.Column,
+                                 getFrontendOpts().DebugCodeCompletionPrinter,
+                                 getFrontendOpts().ShowMacrosInCodeCompletion,
+                                 llvm::outs()));
+
+  if (CompletionConsumer->isOutputBinary() &&
+      llvm::sys::Program::ChangeStdoutToBinary()) {
+    getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
+    CompletionConsumer.reset();
+  }
+}
+
+void CompilerInstance::createFrontendTimer() {
+  FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
+}
+
+CodeCompleteConsumer *
+CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
+                                               const std::string &Filename,
+                                               unsigned Line,
+                                               unsigned Column,
+                                               bool UseDebugPrinter,
+                                               bool ShowMacros,
+                                               llvm::raw_ostream &OS) {
+  // Tell the source manager to chop off the given file at a specific
+  // line and column.
+  const FileEntry *Entry = PP.getFileManager().getFile(Filename);
+  if (!Entry) {
+    PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
+      << Filename;
+    return 0;
+  }
+
+  // Truncate the named file at the given line/column.
+  PP.SetCodeCompletionPoint(Entry, Line, Column);
+
+  // Set up the creation routine for code-completion.
+  if (UseDebugPrinter)
+    return new PrintingCodeCompleteConsumer(ShowMacros, OS);
+  else
+    return new CIndexCodeCompleteConsumer(ShowMacros, OS);
+}
+
+// Output Files
+
+void CompilerInstance::addOutputFile(llvm::StringRef Path,
+                                     llvm::raw_ostream *OS) {
+  assert(OS && "Attempt to add empty stream to output list!");
+  OutputFiles.push_back(std::make_pair(Path, OS));
+}
+
+void CompilerInstance::ClearOutputFiles(bool EraseFiles) {
+  for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
+         it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
+    delete it->second;
+    if (EraseFiles && !it->first.empty())
+      llvm::sys::Path(it->first).eraseFromDisk();
+  }
+  OutputFiles.clear();
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createDefaultOutputFile(bool Binary,
+                                          llvm::StringRef InFile,
+                                          llvm::StringRef Extension) {
+  return createOutputFile(getFrontendOpts().OutputFile, Binary,
+                          InFile, Extension);
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+                                   bool Binary,
+                                   llvm::StringRef InFile,
+                                   llvm::StringRef Extension) {
+  std::string Error, OutputPathName;
+  llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
+                                              InFile, Extension,
+                                              &OutputPathName);
+  if (!OS) {
+    getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+      << OutputPath << Error;
+    return 0;
+  }
+
+  // Add the output file -- but don't try to remove "-", since this means we are
+  // using stdin.
+  addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
+
+  return OS;
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+                                   std::string &Error,
+                                   bool Binary,
+                                   llvm::StringRef InFile,
+                                   llvm::StringRef Extension,
+                                   std::string *ResultPathName) {
+  std::string OutFile;
+  if (!OutputPath.empty()) {
+    OutFile = OutputPath;
+  } else if (InFile == "-") {
+    OutFile = "-";
+  } else if (!Extension.empty()) {
+    llvm::sys::Path Path(InFile);
+    Path.eraseSuffix();
+    Path.appendSuffix(Extension);
+    OutFile = Path.str();
+  } else {
+    OutFile = "-";
+  }
+
+  llvm::OwningPtr<llvm::raw_fd_ostream> OS(
+    new llvm::raw_fd_ostream(OutFile.c_str(), Error,
+                             (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
+  if (!Error.empty())
+    return 0;
+
+  if (ResultPathName)
+    *ResultPathName = OutFile;
+
+  return OS.take();
+}
+
+// Initialization Utilities
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
+  return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
+                                 getSourceManager(), getFrontendOpts());
+}
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
+                                               Diagnostic &Diags,
+                                               FileManager &FileMgr,
+                                               SourceManager &SourceMgr,
+                                               const FrontendOptions &Opts) {
+  // Figure out where to get and map in the main file.
+  if (Opts.EmptyInputOnly) {
+    const char *EmptyStr = "";
+    llvm::MemoryBuffer *SB =
+      llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
+    SourceMgr.createMainFileIDForMemBuffer(SB);
+  } else if (InputFile != "-") {
+    const FileEntry *File = FileMgr.getFile(InputFile);
+    if (File) SourceMgr.createMainFileID(File, SourceLocation());
+    if (SourceMgr.getMainFileID().isInvalid()) {
+      Diags.Report(diag::err_fe_error_reading) << InputFile;
+      return false;
+    }
+  } else {
+    llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
+    SourceMgr.createMainFileIDForMemBuffer(SB);
+    if (SourceMgr.getMainFileID().isInvalid()) {
+      Diags.Report(diag::err_fe_error_reading_stdin);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+// High-Level Operations
+
+bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
+  assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
+  assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
+  assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
+
+  // FIXME: Take this as an argument, once all the APIs we used have moved to
+  // taking it as an input instead of hard-coding llvm::errs.
+  llvm::raw_ostream &OS = llvm::errs();
+
+  // Create the target instance.
+  setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
+  if (!hasTarget())
+    return false;
+
+  // Inform the target of the language options.
+  //
+  // FIXME: We shouldn't need to do this, the target should be immutable once
+  // created. This complexity should be lifted elsewhere.
+  getTarget().setForcedLangOptions(getLangOpts());
+
+  // Validate/process some options.
+  if (getHeaderSearchOpts().Verbose)
+    OS << "clang -cc1 version " CLANG_VERSION_STRING
+       << " based upon " << PACKAGE_STRING
+       << " hosted on " << llvm::sys::getHostTriple() << "\n";
+
+  if (getFrontendOpts().ShowTimers)
+    createFrontendTimer();
+
+  for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
+    const std::string &InFile = getFrontendOpts().Inputs[i].second;
+
+    // If we aren't using an AST file, setup the file and source managers and
+    // the preprocessor.
+    bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
+    if (!IsAST) {
+      if (!i) {
+        // Create a file manager object to provide access to and cache the
+        // filesystem.
+        createFileManager();
+
+        // Create the source manager.
+        createSourceManager();
+      } else {
+        // Reset the ID tables if we are reusing the SourceManager.
+        getSourceManager().clearIDTables();
+      }
+
+      // Create the preprocessor.
+      createPreprocessor();
+    }
+
+    if (Act.BeginSourceFile(*this, InFile, IsAST)) {
+      Act.Execute();
+      Act.EndSourceFile();
+    }
+  }
+
+  if (getDiagnosticOpts().ShowCarets)
+    if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics())
+      OS << NumDiagnostics << " diagnostic"
+         << (NumDiagnostics == 1 ? "" : "s")
+         << " generated.\n";
+
+  if (getFrontendOpts().ShowStats) {
+    getFileManager().PrintStats();
+    OS << "\n";
+  }
+
+  // Return the appropriate status when verifying diagnostics.
+  //
+  // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
+  // this.
+  if (getDiagnosticOpts().VerifyDiagnostics)
+    return !static_cast<VerifyDiagnosticsClient&>(
+      getDiagnosticClient()).HadErrors();
+
+  return !getDiagnostics().getNumErrors();
+}
+
+
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
new file mode 100644
index 0000000..35cfee8
--- /dev/null
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -0,0 +1,1327 @@
+//===--- CompilerInvocation.cpp -------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/Version.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/LangStandard.h"
+#include "clang/Frontend/PCHReader.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Path.h"
+using namespace clang;
+
+static const char *getAnalysisName(Analyses Kind) {
+  switch (Kind) {
+  default:
+    llvm_unreachable("Unknown analysis kind!");
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
+  case NAME: return "-" CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+  }
+}
+
+static const char *getAnalysisStoreName(AnalysisStores Kind) {
+  switch (Kind) {
+  default:
+    llvm_unreachable("Unknown analysis store!");
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+  case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+  }
+}
+
+static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
+  switch (Kind) {
+  default:
+    llvm_unreachable("Unknown analysis constraints!");
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+  case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+  }
+}
+
+static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
+  switch (Kind) {
+  default:
+    llvm_unreachable("Unknown analysis client!");
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
+  case PD_##NAME: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Serialization (to args)
+//===----------------------------------------------------------------------===//
+
+static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
+                               std::vector<std::string> &Res) {
+  for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
+    Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
+  if (Opts.AnalysisStoreOpt != BasicStoreModel) {
+    Res.push_back("-analyzer-store");
+    Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
+  }
+  if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
+    Res.push_back("-analyzer-constraints");
+    Res.push_back(getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
+  }
+  if (Opts.AnalysisDiagOpt != PD_HTML) {
+    Res.push_back("-analyzer-output");
+    Res.push_back(getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
+  }
+  if (!Opts.AnalyzeSpecificFunction.empty()) {
+    Res.push_back("-analyze-function");
+    Res.push_back(Opts.AnalyzeSpecificFunction);
+  }
+  if (Opts.AnalyzeAll)
+    Res.push_back("-analyzer-opt-analyze-headers");
+  if (Opts.AnalyzerDisplayProgress)
+    Res.push_back("-analyzer-display-progress");
+  if (Opts.AnalyzeNestedBlocks)
+    Res.push_back("-analyzer-opt-analyze-nested-blocks");
+  if (Opts.EagerlyAssume)
+    Res.push_back("-analyzer-eagerly-assume");
+  if (!Opts.PurgeDead)
+    Res.push_back("-analyzer-no-purge-dead");
+  if (Opts.TrimGraph)
+    Res.push_back("-trim-egraph");
+  if (Opts.VisualizeEGDot)
+    Res.push_back("-analyzer-viz-egraph-graphviz");
+  if (Opts.VisualizeEGDot)
+    Res.push_back("-analyzer-viz-egraph-ubigraph");
+  if (Opts.EnableExperimentalChecks)
+    Res.push_back("-analyzer-experimental-checks");
+  if (Opts.EnableExperimentalInternalChecks)
+    Res.push_back("-analyzer-experimental-internal-checks");
+}
+
+static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
+                              std::vector<std::string> &Res) {
+  if (Opts.DebugInfo)
+    Res.push_back("-g");
+  if (Opts.DisableLLVMOpts)
+    Res.push_back("-disable-llvm-optzns");
+  if (Opts.DisableRedZone)
+    Res.push_back("-disable-red-zone");
+  if (!Opts.DwarfDebugFlags.empty()) {
+    Res.push_back("-dwarf-debug-flags");
+    Res.push_back(Opts.DwarfDebugFlags);
+  }
+  if (!Opts.MergeAllConstants)
+    Res.push_back("-fno-merge-all-constants");
+  if (Opts.NoCommon)
+    Res.push_back("-fno-common");
+  if (Opts.NoImplicitFloat)
+    Res.push_back("-no-implicit-float");
+  if (Opts.OptimizeSize) {
+    assert(Opts.OptimizationLevel == 2 && "Invalid options!");
+    Res.push_back("-Os");
+  } else if (Opts.OptimizationLevel != 0)
+    Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel));
+  if (!Opts.MainFileName.empty()) {
+    Res.push_back("-main-file-name");
+    Res.push_back(Opts.MainFileName);
+  }
+  // SimplifyLibCalls is only derived.
+  // TimePasses is only derived.
+  // UnitAtATime is unused.
+  // UnrollLoops is only derived.
+  // VerifyModule is only derived.
+  // Inlining is only derived.
+
+  if (Opts.AsmVerbose)
+    Res.push_back("-masm-verbose");
+  if (!Opts.CodeModel.empty()) {
+    Res.push_back("-mcode-model");
+    Res.push_back(Opts.CodeModel);
+  }
+  if (!Opts.DebugPass.empty()) {
+    Res.push_back("-mdebug-pass");
+    Res.push_back(Opts.DebugPass);
+  }
+  if (Opts.DisableFPElim)
+    Res.push_back("-mdisable-fp-elim");
+  if (!Opts.FloatABI.empty()) {
+    Res.push_back("-mfloat-abi");
+    Res.push_back(Opts.FloatABI);
+  }
+  if (!Opts.LimitFloatPrecision.empty()) {
+    Res.push_back("-mlimit-float-precision");
+    Res.push_back(Opts.LimitFloatPrecision);
+  }
+  if (Opts.NoZeroInitializedInBSS)
+    Res.push_back("-mno-zero-initialized-bss");
+  if (Opts.ObjCLegacyDispatch)
+    Res.push_back("-fobjc-legacy-dispatch");
+  if (Opts.SoftFloat)
+    Res.push_back("-msoft-float");
+  if (Opts.UnwindTables)
+    Res.push_back("-munwind-tables");
+  if (Opts.RelocationModel != "pic") {
+    Res.push_back("-mrelocation-model");
+    Res.push_back(Opts.RelocationModel);
+  }
+}
+
+static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
+                                       std::vector<std::string> &Res) {
+  if (Opts.IncludeSystemHeaders)
+    Res.push_back("-sys-header-deps");
+  if (Opts.UsePhonyTargets)
+    Res.push_back("-MP");
+  if (!Opts.OutputFile.empty()) {
+    Res.push_back("-dependency-file");
+    Res.push_back(Opts.OutputFile);
+  }
+  for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i) {
+    Res.push_back("-MT");
+    Res.push_back(Opts.Targets[i]);
+  }
+}
+
+static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
+                                 std::vector<std::string> &Res) {
+  if (Opts.IgnoreWarnings)
+    Res.push_back("-w");
+  if (Opts.NoRewriteMacros)
+    Res.push_back("-Wno-rewrite-macros");
+  if (Opts.Pedantic)
+    Res.push_back("-pedantic");
+  if (Opts.PedanticErrors)
+    Res.push_back("-pedantic-errors");
+  if (!Opts.ShowColumn)
+    Res.push_back("-fno-show-column");
+  if (!Opts.ShowLocation)
+    Res.push_back("-fno-show-source-location");
+  if (!Opts.ShowCarets)
+    Res.push_back("-fno-caret-diagnostics");
+  if (!Opts.ShowFixits)
+    Res.push_back("-fno-diagnostics-fixit-info");
+  if (Opts.ShowSourceRanges)
+    Res.push_back("-fdiagnostics-print-source-range-info");
+  if (Opts.ShowColors)
+    Res.push_back("-fcolor-diagnostics");
+  if (Opts.VerifyDiagnostics)
+    Res.push_back("-verify");
+  if (Opts.BinaryOutput)
+    Res.push_back("-fdiagnostics-binary");
+  if (Opts.ShowOptionNames)
+    Res.push_back("-fdiagnostics-show-option");
+  if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) {
+    Res.push_back("-ftabstop");
+    Res.push_back(llvm::utostr(Opts.TabStop));
+  }
+  if (Opts.MessageLength) {
+    Res.push_back("-fmessage-length");
+    Res.push_back(llvm::utostr(Opts.MessageLength));
+  }
+  if (!Opts.DumpBuildInformation.empty()) {
+    Res.push_back("-dump-build-information");
+    Res.push_back(Opts.DumpBuildInformation);
+  }
+  for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
+    Res.push_back("-W" + Opts.Warnings[i]);
+}
+
+static const char *getInputKindName(FrontendOptions::InputKind Kind) {
+  switch (Kind) {
+  case FrontendOptions::IK_None:              break;
+  case FrontendOptions::IK_AST:               return "ast";
+  case FrontendOptions::IK_Asm:               return "assembler-with-cpp";
+  case FrontendOptions::IK_C:                 return "c";
+  case FrontendOptions::IK_CXX:               return "c++";
+  case FrontendOptions::IK_ObjC:              return "objective-c";
+  case FrontendOptions::IK_ObjCXX:            return "objective-c++";
+  case FrontendOptions::IK_OpenCL:            return "cl";
+  case FrontendOptions::IK_PreprocessedC:     return "cpp-output";
+  case FrontendOptions::IK_PreprocessedCXX:   return "c++-cpp-output";
+  case FrontendOptions::IK_PreprocessedObjC:  return "objective-c-cpp-output";
+  case FrontendOptions::IK_PreprocessedObjCXX:return "objective-c++-cpp-output";
+  }
+
+  llvm_unreachable("Unexpected language kind!");
+  return 0;
+}
+
+static const char *getActionName(frontend::ActionKind Kind) {
+  switch (Kind) {
+  case frontend::PluginAction:
+  case frontend::InheritanceView:
+    llvm_unreachable("Invalid kind!");
+
+  case frontend::ASTDump:                return "-ast-dump";
+  case frontend::ASTPrint:               return "-ast-print";
+  case frontend::ASTPrintXML:            return "-ast-print-xml";
+  case frontend::ASTView:                return "-ast-view";
+  case frontend::DumpRawTokens:          return "-dump-raw-tokens";
+  case frontend::DumpRecordLayouts:      return "-dump-record-layouts";
+  case frontend::DumpTokens:             return "-dump-tokens";
+  case frontend::EmitAssembly:           return "-S";
+  case frontend::EmitBC:                 return "-emit-llvm-bc";
+  case frontend::EmitHTML:               return "-emit-html";
+  case frontend::EmitLLVM:               return "-emit-llvm";
+  case frontend::EmitLLVMOnly:           return "-emit-llvm-only";
+  case frontend::EmitObj:                return "-emit-obj";
+  case frontend::FixIt:                  return "-fixit";
+  case frontend::GeneratePCH:            return "-emit-pch";
+  case frontend::GeneratePTH:            return "-emit-pth";
+  case frontend::ParseNoop:              return "-parse-noop";
+  case frontend::ParsePrintCallbacks:    return "-parse-print-callbacks";
+  case frontend::ParseSyntaxOnly:        return "-fsyntax-only";
+  case frontend::PrintDeclContext:       return "-print-decl-contexts";
+  case frontend::PrintPreprocessedInput: return "-E";
+  case frontend::RewriteMacros:          return "-rewrite-macros";
+  case frontend::RewriteObjC:            return "-rewrite-objc";
+  case frontend::RewriteTest:            return "-rewrite-test";
+  case frontend::RunAnalysis:            return "-analyze";
+  case frontend::RunPreprocessorOnly:    return "-Eonly";
+  }
+
+  llvm_unreachable("Unexpected language kind!");
+  return 0;
+}
+
+static void FrontendOptsToArgs(const FrontendOptions &Opts,
+                               std::vector<std::string> &Res) {
+  if (!Opts.DebugCodeCompletionPrinter)
+    Res.push_back("-no-code-completion-debug-printer");
+  if (Opts.DisableFree)
+    Res.push_back("-disable-free");
+  if (Opts.EmptyInputOnly)
+    Res.push_back("-empty-input-only");
+  if (Opts.RelocatablePCH)
+    Res.push_back("-relocatable-pch");
+  if (Opts.ShowHelp)
+    Res.push_back("-help");
+  if (Opts.ShowMacrosInCodeCompletion)
+    Res.push_back("-code-completion-macros");
+  if (Opts.ShowStats)
+    Res.push_back("-print-stats");
+  if (Opts.ShowTimers)
+    Res.push_back("-ftime-report");
+  if (Opts.ShowVersion)
+    Res.push_back("-version");
+
+  bool NeedLang = false;
+  for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
+    if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].second) !=
+        Opts.Inputs[i].first)
+      NeedLang = true;
+  if (NeedLang) {
+    Res.push_back("-x");
+    Res.push_back(getInputKindName(Opts.Inputs[0].first));
+  }
+  for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
+    assert((!NeedLang || Opts.Inputs[i].first == Opts.Inputs[0].first) &&
+           "Unable to represent this input vector!");
+    Res.push_back(Opts.Inputs[i].second);
+  }
+
+  if (!Opts.OutputFile.empty()) {
+    Res.push_back("-o");
+    Res.push_back(Opts.OutputFile);
+  }
+  if (!Opts.ViewClassInheritance.empty()) {
+    Res.push_back("-cxx-inheritance-view");
+    Res.push_back(Opts.ViewClassInheritance);
+  }
+  for (unsigned i = 0, e = Opts.FixItLocations.size(); i != e; ++i) {
+    Res.push_back("-fixit-at");
+    Res.push_back(Opts.FixItLocations[i].FileName + ":" +
+                  llvm::utostr(Opts.FixItLocations[i].Line) + ":" +
+                  llvm::utostr(Opts.FixItLocations[i].Column));
+  }
+  if (!Opts.CodeCompletionAt.FileName.empty()) {
+    Res.push_back("-code-completion-at");
+    Res.push_back(Opts.CodeCompletionAt.FileName + ":" +
+                  llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
+                  llvm::utostr(Opts.CodeCompletionAt.Column));
+  }
+  if (Opts.ProgramAction != frontend::InheritanceView &&
+      Opts.ProgramAction != frontend::PluginAction)
+    Res.push_back(getActionName(Opts.ProgramAction));
+  if (!Opts.ActionName.empty()) {
+    Res.push_back("-plugin");
+    Res.push_back(Opts.ActionName);
+  }
+  for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i) {
+    Res.push_back("-load");
+    Res.push_back(Opts.Plugins[i]);
+  }
+  for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i) {
+    Res.push_back("-ast-merge");
+    Res.push_back(Opts.ASTMergeFiles[i]);
+  }
+}
+
+static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
+                                   std::vector<std::string> &Res) {
+  if (Opts.Sysroot != "/") {
+    Res.push_back("-isysroot");
+    Res.push_back(Opts.Sysroot);
+  }
+
+  /// User specified include entries.
+  for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
+    const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
+    if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied))
+      llvm::llvm_report_error("Invalid option set!");
+    if (E.IsUserSupplied) {
+      if (E.Group == frontend::After) {
+        Res.push_back("-idirafter");
+      } else if (E.Group == frontend::Quoted) {
+        Res.push_back("-iquote");
+      } else if (E.Group == frontend::System) {
+        Res.push_back("-isystem");
+      } else {
+        assert(E.Group == frontend::Angled && "Invalid group!");
+        Res.push_back(E.IsFramework ? "-F" : "-I");
+      }
+    } else {
+      if (E.Group != frontend::Angled && E.Group != frontend::System)
+        llvm::llvm_report_error("Invalid option set!");
+      Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
+                    "-iwithprefix");
+    }
+    Res.push_back(E.Path);
+  }
+
+  if (!Opts.EnvIncPath.empty()) {
+    // FIXME: Provide an option for this, and move env detection to driver.
+    llvm::llvm_report_error("Not yet implemented!");
+  }
+  if (!Opts.CEnvIncPath.empty()) {
+    // FIXME: Provide an option for this, and move env detection to driver.
+    llvm::llvm_report_error("Not yet implemented!");
+  }
+  if (!Opts.ObjCEnvIncPath.empty()) {
+    // FIXME: Provide an option for this, and move env detection to driver.
+    llvm::llvm_report_error("Not yet implemented!");
+  }
+  if (!Opts.CXXEnvIncPath.empty()) {
+    // FIXME: Provide an option for this, and move env detection to driver.
+    llvm::llvm_report_error("Not yet implemented!");
+  }
+  if (!Opts.ObjCXXEnvIncPath.empty()) {
+    // FIXME: Provide an option for this, and move env detection to driver.
+    llvm::llvm_report_error("Not yet implemented!");
+  }
+  if (!Opts.ResourceDir.empty()) {
+    Res.push_back("-resource-dir");
+    Res.push_back(Opts.ResourceDir);
+  }
+  if (!Opts.UseStandardIncludes)
+    Res.push_back("-nostdinc");
+  if (Opts.Verbose)
+    Res.push_back("-v");
+}
+
+static void LangOptsToArgs(const LangOptions &Opts,
+                           std::vector<std::string> &Res) {
+  LangOptions DefaultLangOpts;
+
+  // FIXME: Need to set -std to get all the implicit options.
+
+  // FIXME: We want to only pass options relative to the defaults, which
+  // requires constructing a target. :(
+  //
+  // It would be better to push the all target specific choices into the driver,
+  // so that everything below that was more uniform.
+
+  if (Opts.Trigraphs)
+    Res.push_back("-trigraphs");
+  // Implicit based on the input kind:
+  //   AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
+  // Implicit based on the input language standard:
+  //   BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
+  if (Opts.DollarIdents)
+    Res.push_back("-fdollars-in-identifiers");
+  if (Opts.Microsoft)
+    Res.push_back("-fms-extensions");
+  if (Opts.ObjCNonFragileABI)
+    Res.push_back("-fobjc-nonfragile-abi");
+  if (Opts.ObjCNonFragileABI2)
+    Res.push_back("-fobjc-nonfragile-abi2");
+  // NoInline is implicit.
+  if (!Opts.CXXOperatorNames)
+    Res.push_back("-fno-operator-names");
+  if (Opts.PascalStrings)
+    Res.push_back("-fpascal-strings");
+  if (Opts.CatchUndefined)
+    Res.push_back("-fcatch-undefined-behavior");
+  if (Opts.WritableStrings)
+    Res.push_back("-fwritable-strings");
+  if (!Opts.LaxVectorConversions)
+    Res.push_back("-fno-lax-vector-conversions");
+  if (Opts.AltiVec)
+    Res.push_back("-faltivec");
+  if (Opts.Exceptions)
+    Res.push_back("-fexceptions");
+  if (!Opts.RTTI)
+    Res.push_back("-fno-rtti");
+  if (!Opts.NeXTRuntime)
+    Res.push_back("-fgnu-runtime");
+  if (Opts.Freestanding)
+    Res.push_back("-ffreestanding");
+  if (Opts.NoBuiltin)
+    Res.push_back("-fno-builtin");
+  if (!Opts.AssumeSaneOperatorNew)
+    Res.push_back("-fno-assume-sane-operator-new");
+  if (!Opts.ThreadsafeStatics)
+    Res.push_back("-fno-threadsafe-statics");
+  if (Opts.POSIXThreads)
+    Res.push_back("-pthread");
+  if (Opts.Blocks)
+    Res.push_back("-fblocks");
+  if (Opts.EmitAllDecls)
+    Res.push_back("-femit-all-decls");
+  if (Opts.MathErrno)
+    Res.push_back("-fmath-errno");
+  if (Opts.OverflowChecking)
+    Res.push_back("-ftrapv");
+  if (Opts.HeinousExtensions)
+    Res.push_back("-fheinous-gnu-extensions");
+  // Optimize is implicit.
+  // OptimizeSize is implicit.
+  if (Opts.Static)
+    Res.push_back("-static-define");
+  if (Opts.PICLevel) {
+    Res.push_back("-pic-level");
+    Res.push_back(llvm::utostr(Opts.PICLevel));
+  }
+  if (Opts.ObjCGCBitmapPrint)
+    Res.push_back("-print-ivar-layout");
+  // FIXME: Don't forget to update when the default changes!
+  if (Opts.AccessControl)
+    Res.push_back("-faccess-control");
+  if (!Opts.CharIsSigned)
+    Res.push_back("-fno-signed-char");
+  if (Opts.ShortWChar)
+    Res.push_back("-fshort-wchar");
+  if (!Opts.ElideConstructors)
+    Res.push_back("-fno-elide-constructors");
+  if (Opts.getGCMode() != LangOptions::NonGC) {
+    if (Opts.getGCMode() == LangOptions::HybridGC) {
+      Res.push_back("-fobjc-gc");
+    } else {
+      assert(Opts.getGCMode() == LangOptions::GCOnly && "Invalid GC mode!");
+      Res.push_back("-fobjc-gc-only");
+    }
+  }
+  if (Opts.getVisibilityMode() != LangOptions::Default) {
+    Res.push_back("-fvisibility");
+    if (Opts.getVisibilityMode() == LangOptions::Hidden) {
+      Res.push_back("hidden");
+    } else {
+      assert(Opts.getVisibilityMode() == LangOptions::Protected &&
+             "Invalid visibility!");
+      Res.push_back("protected");
+    }
+  }
+  if (Opts.getStackProtectorMode() != 0) {
+    Res.push_back("-stack-protector");
+    Res.push_back(llvm::utostr(Opts.getStackProtectorMode()));
+  }
+  if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth) {
+    Res.push_back("-ftemplate-depth");
+    Res.push_back(llvm::utostr(Opts.InstantiationDepth));
+  }
+  if (!Opts.ObjCConstantStringClass.empty()) {
+    Res.push_back("-fconstant-string-class");
+    Res.push_back(Opts.ObjCConstantStringClass);
+  }
+}
+
+static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
+                                   std::vector<std::string> &Res) {
+  for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
+    Res.push_back(std::string(Opts.Macros[i].second ? "-U" : "-D") +
+                  Opts.Macros[i].first);
+  for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
+    // FIXME: We need to avoid reincluding the implicit PCH and PTH includes.
+    Res.push_back("-include");
+    Res.push_back(Opts.Includes[i]);
+  }
+  for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) {
+    Res.push_back("-imacros");
+    Res.push_back(Opts.MacroIncludes[i]);
+  }
+  if (!Opts.UsePredefines)
+    Res.push_back("-undef");
+  if (!Opts.ImplicitPCHInclude.empty()) {
+    Res.push_back("-include-pch");
+    Res.push_back(Opts.ImplicitPCHInclude);
+  }
+  if (!Opts.ImplicitPTHInclude.empty()) {
+    Res.push_back("-include-pth");
+    Res.push_back(Opts.ImplicitPTHInclude);
+  }
+  if (!Opts.TokenCache.empty()) {
+    if (Opts.ImplicitPTHInclude.empty()) {
+      Res.push_back("-token-cache");
+      Res.push_back(Opts.TokenCache);
+    } else
+      assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
+             "Unsupported option combination!");
+  }
+  for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
+    Res.push_back("-remap-file");
+    Res.push_back(Opts.RemappedFiles[i].first + ";" +
+                  Opts.RemappedFiles[i].second);
+  }
+}
+
+static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
+                                         std::vector<std::string> &Res) {
+  if (!Opts.ShowCPP && !Opts.ShowMacros)
+    llvm::llvm_report_error("Invalid option combination!");
+
+  if (Opts.ShowCPP && Opts.ShowMacros)
+    Res.push_back("-dD");
+  else if (!Opts.ShowCPP && Opts.ShowMacros)
+    Res.push_back("-dM");
+
+  if (!Opts.ShowLineMarkers)
+    Res.push_back("-P");
+  if (Opts.ShowComments)
+    Res.push_back("-C");
+  if (Opts.ShowMacroComments)
+    Res.push_back("-CC");
+}
+
+static void TargetOptsToArgs(const TargetOptions &Opts,
+                             std::vector<std::string> &Res) {
+  Res.push_back("-triple");
+  Res.push_back(Opts.Triple);
+  if (!Opts.CPU.empty()) {
+    Res.push_back("-target-cpu");
+    Res.push_back(Opts.CPU);
+  }
+  if (!Opts.ABI.empty()) {
+    Res.push_back("-target-abi");
+    Res.push_back(Opts.ABI);
+  }
+  for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
+    Res.push_back("-target-feature");
+    Res.push_back(Opts.Features[i]);
+  }
+}
+
+void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
+  AnalyzerOptsToArgs(getAnalyzerOpts(), Res);
+  CodeGenOptsToArgs(getCodeGenOpts(), Res);
+  DependencyOutputOptsToArgs(getDependencyOutputOpts(), Res);
+  DiagnosticOptsToArgs(getDiagnosticOpts(), Res);
+  FrontendOptsToArgs(getFrontendOpts(), Res);
+  HeaderSearchOptsToArgs(getHeaderSearchOpts(), Res);
+  LangOptsToArgs(getLangOpts(), Res);
+  PreprocessorOptsToArgs(getPreprocessorOpts(), Res);
+  PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), Res);
+  TargetOptsToArgs(getTargetOpts(), Res);
+}
+
+//===----------------------------------------------------------------------===//
+// Deserialization (to args)
+//===----------------------------------------------------------------------===//
+
+using namespace clang::driver;
+using namespace clang::driver::cc1options;
+
+static llvm::StringRef getLastArgValue(ArgList &Args, cc1options::ID ID,
+                                       llvm::StringRef Default = "") {
+  if (Arg *A = Args.getLastArg(ID))
+    return A->getValue(Args);
+  return Default;
+}
+
+static int getLastArgIntValue(ArgList &Args, cc1options::ID ID,
+                              int Default, Diagnostic &Diags) {
+  Arg *A = Args.getLastArg(ID);
+  if (!A)
+    return Default;
+
+  int Res = Default;
+  if (llvm::StringRef(A->getValue(Args)).getAsInteger(10, Res))
+    Diags.Report(diag::err_drv_invalid_int_value)
+        << A->getAsString(Args) << A->getValue(Args);
+
+  return Res;
+}
+
+static std::vector<std::string>
+getAllArgValues(ArgList &Args, cc1options::ID ID) {
+  llvm::SmallVector<const char *, 16> Values;
+  Args.AddAllArgValues(Values, ID);
+  return std::vector<std::string>(Values.begin(), Values.end());
+}
+
+//
+
+static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
+                              Diagnostic &Diags) {
+  using namespace cc1options;
+
+  Opts.AnalysisList.clear();
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) \
+  if (Args.hasArg(OPT_analysis_##NAME)) Opts.AnalysisList.push_back(NAME);
+#include "clang/Frontend/Analyses.def"
+
+  if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
+    llvm::StringRef Name = A->getValue(Args);
+    AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+      .Case(CMDFLAG, NAME##Model)
+#include "clang/Frontend/Analyses.def"
+      .Default(NumStores);
+    // FIXME: Error handling.
+    if (Value == NumStores)
+      Diags.Report(diag::err_drv_invalid_value)
+        << Args.getLastArg(OPT_O)->getAsString(Args) << Name;
+    else
+      Opts.AnalysisStoreOpt = Value;
+  }
+
+  if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
+    llvm::StringRef Name = A->getValue(Args);
+    AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+      .Case(CMDFLAG, NAME##Model)
+#include "clang/Frontend/Analyses.def"
+      .Default(NumConstraints);
+    // FIXME: Error handling.
+    if (Value == NumConstraints)
+      Diags.Report(diag::err_drv_invalid_value)
+        << Args.getLastArg(OPT_O)->getAsString(Args) << Name;
+    else
+      Opts.AnalysisConstraintsOpt = Value;
+  }
+
+  if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
+    llvm::StringRef Name = A->getValue(Args);
+    AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \
+      .Case(CMDFLAG, PD_##NAME)
+#include "clang/Frontend/Analyses.def"
+      .Default(NUM_ANALYSIS_DIAG_CLIENTS);
+    // FIXME: Error handling.
+    if (Value == NUM_ANALYSIS_DIAG_CLIENTS)
+      Diags.Report(diag::err_drv_invalid_value)
+        << Args.getLastArg(OPT_O)->getAsString(Args) << Name;
+    else
+      Opts.AnalysisDiagOpt = Value;
+  }
+
+  Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
+  Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
+  Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
+  Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+  Opts.AnalyzeNestedBlocks =
+    Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
+  Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead);
+  Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
+  Opts.AnalyzeSpecificFunction = getLastArgValue(Args, OPT_analyze_function);
+  Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks);
+  Opts.EnableExperimentalInternalChecks =
+    Args.hasArg(OPT_analyzer_experimental_internal_checks);
+  Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
+}
+
+static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
+                             Diagnostic &Diags) {
+  using namespace cc1options;
+  // -Os implies -O2
+  if (Args.hasArg(OPT_Os))
+    Opts.OptimizationLevel = 2;
+  else {
+    Opts.OptimizationLevel = getLastArgIntValue(Args, OPT_O, 0, Diags);
+    if (Opts.OptimizationLevel > 3) {
+      Diags.Report(diag::err_drv_invalid_value)
+        << Args.getLastArg(OPT_O)->getAsString(Args) << Opts.OptimizationLevel;
+      Opts.OptimizationLevel = 3;
+    }
+  }
+
+  // We must always run at least the always inlining pass.
+  Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
+    : CodeGenOptions::OnlyAlwaysInlining;
+
+  Opts.DebugInfo = Args.hasArg(OPT_g);
+  Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
+  Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
+  Opts.DwarfDebugFlags = getLastArgValue(Args, OPT_dwarf_debug_flags);
+  Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
+  Opts.NoCommon = Args.hasArg(OPT_fno_common);
+  Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
+  Opts.OptimizeSize = Args.hasArg(OPT_Os);
+  Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
+
+  Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
+  Opts.CodeModel = getLastArgValue(Args, OPT_mcode_model);
+  Opts.DebugPass = getLastArgValue(Args, OPT_mdebug_pass);
+  Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
+  Opts.FloatABI = getLastArgValue(Args, OPT_mfloat_abi);
+  Opts.LimitFloatPrecision = getLastArgValue(Args, OPT_mlimit_float_precision);
+  Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
+  Opts.ObjCLegacyDispatch = Args.hasArg(OPT_fobjc_legacy_dispatch);
+  Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
+  Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
+  Opts.RelocationModel = getLastArgValue(Args, OPT_mrelocation_model, "pic");
+
+  Opts.MainFileName = getLastArgValue(Args, OPT_main_file_name);
+
+  // FIXME: Put elsewhere?
+#ifdef NDEBUG
+  Opts.VerifyModule = 0;
+#else
+  Opts.VerifyModule = 1;
+#endif
+}
+
+static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
+                                      ArgList &Args) {
+  using namespace cc1options;
+  Opts.OutputFile = getLastArgValue(Args, OPT_dependency_file);
+  Opts.Targets = getAllArgValues(Args, OPT_MT);
+  Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
+  Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
+}
+
+static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+                                Diagnostic &Diags) {
+  using namespace cc1options;
+  Opts.IgnoreWarnings = Args.hasArg(OPT_w);
+  Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
+  Opts.Pedantic = Args.hasArg(OPT_pedantic);
+  Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
+  Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
+  Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics);
+  Opts.ShowColumn = !Args.hasArg(OPT_fno_show_column);
+  Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
+  Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
+  Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option);
+  Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
+  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+  Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary);
+  Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
+                                    DiagnosticOptions::DefaultTabStop, Diags);
+  if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
+    Diags.Report(diag::warn_ignoring_ftabstop_value)
+      << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
+    Opts.TabStop = DiagnosticOptions::DefaultTabStop;
+  }
+  Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags);
+  Opts.DumpBuildInformation = getLastArgValue(Args, OPT_dump_build_information);
+  Opts.Warnings = getAllArgValues(Args, OPT_W);
+}
+
+static FrontendOptions::InputKind
+ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) {
+  using namespace cc1options;
+  Opts.ProgramAction = frontend::ParseSyntaxOnly;
+  if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
+    switch (A->getOption().getID()) {
+    default:
+      assert(0 && "Invalid option in group!");
+    case OPT_ast_dump:
+      Opts.ProgramAction = frontend::ASTDump; break;
+    case OPT_ast_print:
+      Opts.ProgramAction = frontend::ASTPrint; break;
+    case OPT_ast_print_xml:
+      Opts.ProgramAction = frontend::ASTPrintXML; break;
+    case OPT_ast_view:
+      Opts.ProgramAction = frontend::ASTView; break;
+    case OPT_dump_raw_tokens:
+      Opts.ProgramAction = frontend::DumpRawTokens; break;
+    case OPT_dump_record_layouts:
+      Opts.ProgramAction = frontend::DumpRecordLayouts; break;
+    case OPT_dump_tokens:
+      Opts.ProgramAction = frontend::DumpTokens; break;
+    case OPT_S:
+      Opts.ProgramAction = frontend::EmitAssembly; break;
+    case OPT_emit_llvm_bc:
+      Opts.ProgramAction = frontend::EmitBC; break;
+    case OPT_emit_html:
+      Opts.ProgramAction = frontend::EmitHTML; break;
+    case OPT_emit_llvm:
+      Opts.ProgramAction = frontend::EmitLLVM; break;
+    case OPT_emit_llvm_only:
+      Opts.ProgramAction = frontend::EmitLLVMOnly; break;
+    case OPT_emit_obj:
+      Opts.ProgramAction = frontend::EmitObj; break;
+    case OPT_fixit:
+      Opts.ProgramAction = frontend::FixIt; break;
+    case OPT_emit_pch:
+      Opts.ProgramAction = frontend::GeneratePCH; break;
+    case OPT_emit_pth:
+      Opts.ProgramAction = frontend::GeneratePTH; break;
+    case OPT_parse_noop:
+      Opts.ProgramAction = frontend::ParseNoop; break;
+    case OPT_parse_print_callbacks:
+      Opts.ProgramAction = frontend::ParsePrintCallbacks; break;
+    case OPT_fsyntax_only:
+      Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
+    case OPT_print_decl_contexts:
+      Opts.ProgramAction = frontend::PrintDeclContext; break;
+    case OPT_E:
+      Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
+    case OPT_rewrite_macros:
+      Opts.ProgramAction = frontend::RewriteMacros; break;
+    case OPT_rewrite_objc:
+      Opts.ProgramAction = frontend::RewriteObjC; break;
+    case OPT_rewrite_test:
+      Opts.ProgramAction = frontend::RewriteTest; break;
+    case OPT_analyze:
+      Opts.ProgramAction = frontend::RunAnalysis; break;
+    case OPT_Eonly:
+      Opts.ProgramAction = frontend::RunPreprocessorOnly; break;
+    }
+  }
+  if (const Arg *A = Args.getLastArg(OPT_plugin)) {
+    Opts.ProgramAction = frontend::PluginAction;
+    Opts.ActionName = A->getValue(Args);
+  }
+
+  if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
+    Opts.CodeCompletionAt =
+      ParsedSourceLocation::FromString(A->getValue(Args));
+    if (Opts.CodeCompletionAt.FileName.empty())
+      Diags.Report(diag::err_drv_invalid_value)
+        << A->getAsString(Args) << A->getValue(Args);
+  }
+  Opts.DebugCodeCompletionPrinter =
+    !Args.hasArg(OPT_no_code_completion_debug_printer);
+  Opts.DisableFree = Args.hasArg(OPT_disable_free);
+  Opts.EmptyInputOnly = Args.hasArg(OPT_empty_input_only);
+
+  Opts.FixItLocations.clear();
+  for (arg_iterator it = Args.filtered_begin(OPT_fixit_at),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    const char *Loc = it->getValue(Args);
+    ParsedSourceLocation PSL = ParsedSourceLocation::FromString(Loc);
+
+    if (PSL.FileName.empty()) {
+      Diags.Report(diag::err_drv_invalid_value) << it->getAsString(Args) << Loc;
+      continue;
+    }
+
+    Opts.FixItLocations.push_back(PSL);
+  }
+
+  Opts.OutputFile = getLastArgValue(Args, OPT_o);
+  Opts.Plugins = getAllArgValues(Args, OPT_load);
+  Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch);
+  Opts.ShowHelp = Args.hasArg(OPT_help);
+  Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
+  Opts.ShowStats = Args.hasArg(OPT_print_stats);
+  Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
+  Opts.ShowVersion = Args.hasArg(OPT_version);
+  Opts.ViewClassInheritance = getLastArgValue(Args, OPT_cxx_inheritance_view);
+  Opts.ASTMergeFiles = getAllArgValues(Args, OPT_ast_merge);
+
+  FrontendOptions::InputKind DashX = FrontendOptions::IK_None;
+  if (const Arg *A = Args.getLastArg(OPT_x)) {
+    DashX = llvm::StringSwitch<FrontendOptions::InputKind>(A->getValue(Args))
+      .Case("c", FrontendOptions::IK_C)
+      .Case("cl", FrontendOptions::IK_OpenCL)
+      .Case("c", FrontendOptions::IK_C)
+      .Case("cl", FrontendOptions::IK_OpenCL)
+      .Case("c++", FrontendOptions::IK_CXX)
+      .Case("objective-c", FrontendOptions::IK_ObjC)
+      .Case("objective-c++", FrontendOptions::IK_ObjCXX)
+      .Case("cpp-output", FrontendOptions::IK_PreprocessedC)
+      .Case("assembler-with-cpp", FrontendOptions::IK_Asm)
+      .Case("c++-cpp-output", FrontendOptions::IK_PreprocessedCXX)
+      .Case("objective-c-cpp-output", FrontendOptions::IK_PreprocessedObjC)
+      .Case("objective-c++-cpp-output", FrontendOptions::IK_PreprocessedObjCXX)
+      .Case("c-header", FrontendOptions::IK_C)
+      .Case("objective-c-header", FrontendOptions::IK_ObjC)
+      .Case("c++-header", FrontendOptions::IK_CXX)
+      .Case("objective-c++-header", FrontendOptions::IK_ObjCXX)
+      .Case("ast", FrontendOptions::IK_AST)
+      .Default(FrontendOptions::IK_None);
+    if (DashX == FrontendOptions::IK_None)
+      Diags.Report(diag::err_drv_invalid_value)
+        << A->getAsString(Args) << A->getValue(Args);
+  }
+
+  // '-' is the default input if none is given.
+  std::vector<std::string> Inputs = getAllArgValues(Args, OPT_INPUT);
+  Opts.Inputs.clear();
+  if (Inputs.empty())
+    Inputs.push_back("-");
+  for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
+    FrontendOptions::InputKind IK = DashX;
+    if (IK == FrontendOptions::IK_None) {
+      IK = FrontendOptions::getInputKindForExtension(
+        llvm::StringRef(Inputs[i]).rsplit('.').second);
+      // FIXME: Remove this hack.
+      if (i == 0)
+        DashX = IK;
+    }
+    Opts.Inputs.push_back(std::make_pair(IK, Inputs[i]));
+  }
+
+  return DashX;
+}
+
+std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
+                                                 void *MainAddr) {
+  llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
+
+  if (!P.isEmpty()) {
+    P.eraseComponent();  // Remove /clang from foo/bin/clang
+    P.eraseComponent();  // Remove /bin   from foo/bin
+
+    // Get foo/lib/clang/<version>/include
+    P.appendComponent("lib");
+    P.appendComponent("clang");
+    P.appendComponent(CLANG_VERSION_STRING);
+  }
+
+  return P.str();
+}
+
+static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
+  using namespace cc1options;
+  Opts.Sysroot = getLastArgValue(Args, OPT_isysroot, "/");
+  Opts.Verbose = Args.hasArg(OPT_v);
+  Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
+  Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc);
+  Opts.ResourceDir = getLastArgValue(Args, OPT_resource_dir);
+
+  // Add -I... and -F... options in order.
+  for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F),
+         ie = Args.filtered_end(); it != ie; ++it)
+    Opts.AddPath(it->getValue(Args), frontend::Angled, true,
+                 /*IsFramework=*/ it->getOption().matches(OPT_F));
+
+  // Add -iprefix/-iwith-prefix/-iwithprefixbefore options.
+  llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
+  for (arg_iterator it = Args.filtered_begin(OPT_iprefix, OPT_iwithprefix,
+                                             OPT_iwithprefixbefore),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    if (it->getOption().matches(OPT_iprefix))
+      Prefix = it->getValue(Args);
+    else if (it->getOption().matches(OPT_iwithprefix))
+      Opts.AddPath(Prefix.str() + it->getValue(Args),
+                   frontend::System, false, false);
+    else
+      Opts.AddPath(Prefix.str() + it->getValue(Args),
+                   frontend::Angled, false, false);
+  }
+
+  for (arg_iterator it = Args.filtered_begin(OPT_idirafter),
+         ie = Args.filtered_end(); it != ie; ++it)
+    Opts.AddPath(it->getValue(Args), frontend::After, true, false);
+  for (arg_iterator it = Args.filtered_begin(OPT_iquote),
+         ie = Args.filtered_end(); it != ie; ++it)
+    Opts.AddPath(it->getValue(Args), frontend::Quoted, true, false);
+  for (arg_iterator it = Args.filtered_begin(OPT_isystem),
+         ie = Args.filtered_end(); it != ie; ++it)
+    Opts.AddPath(it->getValue(Args), frontend::System, true, false);
+
+  // FIXME: Need options for the various environment variables!
+}
+
+static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
+                          FrontendOptions::InputKind IK,
+                          Diagnostic &Diags) {
+  // FIXME: Cleanup per-file based stuff.
+
+  // Set some properties which depend soley on the input kind; it would be nice
+  // to move these to the language standard, and have the driver resolve the
+  // input kind + language standard.
+  if (IK == FrontendOptions::IK_Asm) {
+    Opts.AsmPreprocessor = 1;
+  } else if (IK == FrontendOptions::IK_ObjC ||
+             IK == FrontendOptions::IK_ObjCXX ||
+             IK == FrontendOptions::IK_PreprocessedObjC ||
+             IK == FrontendOptions::IK_PreprocessedObjCXX) {
+    Opts.ObjC1 = Opts.ObjC2 = 1;
+  }
+
+  LangStandard::Kind LangStd = LangStandard::lang_unspecified;
+  if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
+    LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args))
+#define LANGSTANDARD(id, name, desc, features) \
+      .Case(name, LangStandard::lang_##id)
+#include "clang/Frontend/LangStandards.def"
+      .Default(LangStandard::lang_unspecified);
+    if (LangStd == LangStandard::lang_unspecified)
+      Diags.Report(diag::err_drv_invalid_value)
+        << A->getAsString(Args) << A->getValue(Args);
+  }
+
+  if (LangStd == LangStandard::lang_unspecified) {
+    // Based on the base language, pick one.
+    switch (IK) {
+    case FrontendOptions::IK_None:
+    case FrontendOptions::IK_AST:
+      assert(0 && "Invalid input kind!");
+    case FrontendOptions::IK_OpenCL:
+      LangStd = LangStandard::lang_opencl;
+      break;
+    case FrontendOptions::IK_Asm:
+    case FrontendOptions::IK_C:
+    case FrontendOptions::IK_PreprocessedC:
+    case FrontendOptions::IK_ObjC:
+    case FrontendOptions::IK_PreprocessedObjC:
+      LangStd = LangStandard::lang_gnu99;
+      break;
+    case FrontendOptions::IK_CXX:
+    case FrontendOptions::IK_PreprocessedCXX:
+    case FrontendOptions::IK_ObjCXX:
+    case FrontendOptions::IK_PreprocessedObjCXX:
+      LangStd = LangStandard::lang_gnucxx98;
+      break;
+    }
+  }
+
+  const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
+  Opts.BCPLComment = Std.hasBCPLComments();
+  Opts.C99 = Std.isC99();
+  Opts.CPlusPlus = Std.isCPlusPlus();
+  Opts.CPlusPlus0x = Std.isCPlusPlus0x();
+  Opts.Digraphs = Std.hasDigraphs();
+  Opts.GNUMode = Std.isGNUMode();
+  Opts.GNUInline = !Std.isC99();
+  Opts.HexFloats = Std.hasHexFloats();
+  Opts.ImplicitInt = Std.hasImplicitInt();
+
+  // OpenCL has some additional defaults.
+  if (LangStd == LangStandard::lang_opencl) {
+    Opts.OpenCL = 1;
+    Opts.AltiVec = 1;
+    Opts.CXXOperatorNames = 1;
+    Opts.LaxVectorConversions = 1;
+  }
+
+  // OpenCL and C++ both have bool, true, false keywords.
+  Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
+
+  if (Opts.CPlusPlus)
+    Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names);
+
+  if (Args.hasArg(OPT_fobjc_gc_only))
+    Opts.setGCMode(LangOptions::GCOnly);
+  else if (Args.hasArg(OPT_fobjc_gc))
+    Opts.setGCMode(LangOptions::HybridGC);
+
+  if (Args.hasArg(OPT_print_ivar_layout))
+    Opts.ObjCGCBitmapPrint = 1;
+
+  if (Args.hasArg(OPT_faltivec))
+    Opts.AltiVec = 1;
+
+  if (Args.hasArg(OPT_pthread))
+    Opts.POSIXThreads = 1;
+
+  llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility,
+                                        "default");
+  if (Vis == "default")
+    Opts.setVisibilityMode(LangOptions::Default);
+  else if (Vis == "hidden")
+    Opts.setVisibilityMode(LangOptions::Hidden);
+  else if (Vis == "protected")
+    Opts.setVisibilityMode(LangOptions::Protected);
+  else
+    Diags.Report(diag::err_drv_invalid_value)
+      << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+
+  Opts.OverflowChecking = Args.hasArg(OPT_ftrapv);
+
+  // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+  // is specified, or -std is set to a conforming mode.
+  Opts.Trigraphs = !Opts.GNUMode;
+  if (Args.hasArg(OPT_trigraphs))
+    Opts.Trigraphs = 1;
+
+  Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
+                                   OPT_fno_dollars_in_identifiers,
+                                   !Opts.AsmPreprocessor);
+  Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
+  Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+  Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
+  if (Args.hasArg(OPT_fno_lax_vector_conversions))
+    Opts.LaxVectorConversions = 0;
+  if (Args.hasArg(OPT_fno_threadsafe_statics))
+    Opts.ThreadsafeStatics = 0;  
+  Opts.Exceptions = Args.hasArg(OPT_fexceptions);
+  Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
+  Opts.Blocks = Args.hasArg(OPT_fblocks);
+  Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
+  Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
+  Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
+  Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
+  Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
+  Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
+  Opts.AccessControl = Args.hasArg(OPT_faccess_control);
+  Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
+  Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
+  Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99,
+                                               Diags);
+  Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
+  Opts.ObjCConstantStringClass = getLastArgValue(Args,
+                                                 OPT_fconstant_string_class);
+  Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
+  Opts.ObjCNonFragileABI2 = Args.hasArg(OPT_fobjc_nonfragile_abi2);
+  if (Opts.ObjCNonFragileABI2)
+    Opts.ObjCNonFragileABI = true;
+  Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
+  Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
+  Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
+  Opts.Static = Args.hasArg(OPT_static_define);
+  Opts.OptimizeSize = 0;
+
+  // FIXME: Eliminate this dependency.
+  unsigned Opt =
+    Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
+  Opts.Optimize = Opt != 0;
+
+  // This is the __NO_INLINE__ define, which just depends on things like the
+  // optimization level and -fno-inline, not actually whether the backend has
+  // inlining enabled.
+  //
+  // FIXME: This is affected by other options (-fno-inline).
+  Opts.NoInline = !Opt;
+
+  unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags);
+  switch (SSP) {
+  default:
+    Diags.Report(diag::err_drv_invalid_value)
+      << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
+    break;
+  case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break;
+  case 1: Opts.setStackProtectorMode(LangOptions::SSPOn);  break;
+  case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break;
+  }
+}
+
+static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
+                                  Diagnostic &Diags) {
+  using namespace cc1options;
+  Opts.ImplicitPCHInclude = getLastArgValue(Args, OPT_include_pch);
+  Opts.ImplicitPTHInclude = getLastArgValue(Args, OPT_include_pth);
+  if (const Arg *A = Args.getLastArg(OPT_token_cache))
+      Opts.TokenCache = A->getValue(Args);
+  else
+    Opts.TokenCache = Opts.ImplicitPTHInclude;
+  Opts.UsePredefines = !Args.hasArg(OPT_undef);
+
+  // Add macros from the command line.
+  for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    if (it->getOption().matches(OPT_D))
+      Opts.addMacroDef(it->getValue(Args));
+    else
+      Opts.addMacroUndef(it->getValue(Args));
+  }
+
+  Opts.MacroIncludes = getAllArgValues(Args, OPT_imacros);
+
+  // Add the ordered list of -includes.
+  for (arg_iterator it = Args.filtered_begin(OPT_include, OPT_include_pch,
+                                             OPT_include_pth),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    // PCH is handled specially, we need to extra the original include path.
+    if (it->getOption().matches(OPT_include_pch)) {
+      std::string OriginalFile =
+        PCHReader::getOriginalSourceFile(it->getValue(Args), Diags);
+      if (OriginalFile.empty())
+        continue;
+
+      Opts.Includes.push_back(OriginalFile);
+    } else
+      Opts.Includes.push_back(it->getValue(Args));
+  }
+
+  for (arg_iterator it = Args.filtered_begin(OPT_remap_file),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    std::pair<llvm::StringRef,llvm::StringRef> Split =
+      llvm::StringRef(it->getValue(Args)).split(';');
+
+    if (Split.second.empty()) {
+      Diags.Report(diag::err_drv_invalid_remap_file) << it->getAsString(Args);
+      continue;
+    }
+
+    Opts.addRemappedFile(Split.first, Split.second);
+  }
+}
+
+static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
+                                        ArgList &Args) {
+  using namespace cc1options;
+  Opts.ShowCPP = !Args.hasArg(OPT_dM);
+  Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+  Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
+  Opts.ShowComments = Args.hasArg(OPT_C);
+  Opts.ShowMacroComments = Args.hasArg(OPT_CC);
+}
+
+static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
+  using namespace cc1options;
+  Opts.ABI = getLastArgValue(Args, OPT_target_abi);
+  Opts.CPU = getLastArgValue(Args, OPT_target_cpu);
+  Opts.Triple = getLastArgValue(Args, OPT_triple);
+  Opts.Features = getAllArgValues(Args, OPT_target_feature);
+
+  // Use the host triple if unspecified.
+  if (Opts.Triple.empty())
+    Opts.Triple = llvm::sys::getHostTriple();
+}
+
+//
+
+void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
+                                        const char **ArgBegin,
+                                        const char **ArgEnd,
+                                        Diagnostic &Diags) {
+  // Parse the arguments.
+  llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::OwningPtr<InputArgList> Args(
+    Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
+
+  // Check for missing argument error.
+  if (MissingArgCount)
+    Diags.Report(diag::err_drv_missing_argument)
+      << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+  // Issue errors on unknown arguments.
+  for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
+         ie = Args->filtered_end(); it != ie; ++it)
+    Diags.Report(diag::err_drv_unknown_argument) << it->getAsString(*Args);
+
+  ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags);
+  ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, Diags);
+  ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
+  ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
+  FrontendOptions::InputKind DashX =
+    ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
+  ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
+  if (DashX != FrontendOptions::IK_AST)
+    ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
+  ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, Diags);
+  ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
+  ParseTargetArgs(Res.getTargetOpts(), *Args);
+}
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
new file mode 100644
index 0000000..d7470d9
--- /dev/null
+++ b/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,137 @@
+//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> {
+  DocumentXML& Doc;
+
+  void addSubNodes(FunctionDecl* FD) {
+    for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+      Visit(FD->getParamDecl(i));
+      Doc.toParent();
+    }
+  }
+
+  void addSubNodes(RecordDecl* RD) {
+    for (RecordDecl::field_iterator i = RD->field_begin(),
+                                    e = RD->field_end(); i != e; ++i) {
+      Visit(*i);
+      Doc.toParent();
+    }
+  }
+
+  void addSubNodes(EnumDecl* ED) {
+    for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
+                                       e = ED->enumerator_end(); i != e; ++i) {
+      Visit(*i);
+      Doc.toParent();
+    }
+  }
+
+  void addSubNodes(EnumConstantDecl* ECD) {
+    if (ECD->getInitExpr())
+      Doc.PrintStmt(ECD->getInitExpr());
+  }
+
+  void addSubNodes(FieldDecl* FdD)  {
+    if (FdD->isBitField())
+      Doc.PrintStmt(FdD->getBitWidth());
+  }
+
+  void addSubNodes(VarDecl* V) {
+    if (V->getInit())
+      Doc.PrintStmt(V->getInit());
+  }
+
+  void addSubNodes(ParmVarDecl* argDecl) {
+    if (argDecl->getDefaultArg())
+      Doc.PrintStmt(argDecl->getDefaultArg());
+  }
+
+  void addSpecialAttribute(const char* pName, EnumDecl* ED) {
+    const QualType& enumType = ED->getIntegerType();
+    if (!enumType.isNull())
+      Doc.addAttribute(pName, enumType);
+  }
+
+  void addIdAttribute(LinkageSpecDecl* ED) {
+    Doc.addAttribute("id", ED);
+  }
+
+  void addIdAttribute(NamedDecl* ND) {
+    Doc.addAttribute("id", ND);
+  }
+
+public:
+  DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* T)            \
+  {                                      \
+    Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML                  addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME )         Doc.addAttribute(NAME, T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )     Doc.addAttributeOptional(NAME, T->FN);
+#define ATTRIBUTE_FILE_LOCATION_XML       Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = false;             \
+    switch (T->FN) {                    \
+    default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = true;              \
+    switch (T->FN) {                    \
+    default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME )         case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML                    } }
+#define END_NODE_XML                    }
+
+#define SUB_NODE_XML( CLASS )           addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS )  addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS )       addSubNodes(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//---------------------------------------------------------
+void DocumentXML::writeDeclToXML(Decl *D) {
+  DeclPrinter(*this).Visit(D);
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (Stmt *Body = FD->getBody()) {
+      addSubNode("Body");
+      PrintStmt(Body);
+      toParent();
+    }
+  }
+  toParent();
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
new file mode 100644
index 0000000..478c339
--- /dev/null
+++ b/lib/Frontend/DependencyFile.cpp
@@ -0,0 +1,174 @@
+//===--- DependencyFile.cpp - Generate dependency file --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code generates dependency files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace clang;
+
+namespace {
+class DependencyFileCallback : public PPCallbacks {
+  std::vector<std::string> Files;
+  llvm::StringSet<> FilesSet;
+  const Preprocessor *PP;
+  std::vector<std::string> Targets;
+  llvm::raw_ostream *OS;
+  bool IncludeSystemHeaders;
+  bool PhonyTarget;
+private:
+  bool FileMatchesDepCriteria(const char *Filename,
+                              SrcMgr::CharacteristicKind FileType);
+  void OutputDependencyFile();
+
+public:
+  DependencyFileCallback(const Preprocessor *_PP,
+                         llvm::raw_ostream *_OS,
+                         const DependencyOutputOptions &Opts)
+    : PP(_PP), Targets(Opts.Targets), OS(_OS),
+      IncludeSystemHeaders(Opts.IncludeSystemHeaders),
+      PhonyTarget(Opts.UsePhonyTargets) {}
+
+  ~DependencyFileCallback() {
+    OutputDependencyFile();
+    OS->flush();
+    delete OS;
+  }
+
+  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+                           SrcMgr::CharacteristicKind FileType);
+};
+}
+
+void clang::AttachDependencyFileGen(Preprocessor &PP,
+                                    const DependencyOutputOptions &Opts) {
+  if (Opts.Targets.empty()) {
+    PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
+    return;
+  }
+
+  std::string Err;
+  llvm::raw_ostream *OS(new llvm::raw_fd_ostream(Opts.OutputFile.c_str(), Err));
+  if (!Err.empty()) {
+    PP.getDiagnostics().Report(diag::err_fe_error_opening)
+      << Opts.OutputFile << Err;
+    return;
+  }
+
+  assert(!PP.getPPCallbacks() && "Preprocessor callbacks already registered!");
+  PP.setPPCallbacks(new DependencyFileCallback(&PP, OS, Opts));
+}
+
+/// FileMatchesDepCriteria - Determine whether the given Filename should be
+/// considered as a dependency.
+bool DependencyFileCallback::FileMatchesDepCriteria(const char *Filename,
+                                          SrcMgr::CharacteristicKind FileType) {
+  if (strcmp("<built-in>", Filename) == 0)
+    return false;
+
+  if (IncludeSystemHeaders)
+    return true;
+
+  return FileType == SrcMgr::C_User;
+}
+
+void DependencyFileCallback::FileChanged(SourceLocation Loc,
+                                         FileChangeReason Reason,
+                                         SrcMgr::CharacteristicKind FileType) {
+  if (Reason != PPCallbacks::EnterFile)
+    return;
+
+  // Dependency generation really does want to go all the way to the
+  // file entry for a source location to find out what is depended on.
+  // We do not want #line markers to affect dependency generation!
+  SourceManager &SM = PP->getSourceManager();
+
+  const FileEntry *FE =
+    SM.getFileEntryForID(SM.getFileID(SM.getInstantiationLoc(Loc)));
+  if (FE == 0) return;
+
+  const char *Filename = FE->getName();
+  if (!FileMatchesDepCriteria(Filename, FileType))
+    return;
+
+  // Remove leading "./"
+  if (Filename[0] == '.' && Filename[1] == '/')
+    Filename = &Filename[2];
+
+  if (FilesSet.insert(Filename))
+    Files.push_back(Filename);
+}
+
+void DependencyFileCallback::OutputDependencyFile() {
+  // Write out the dependency targets, trying to avoid overly long
+  // lines when possible. We try our best to emit exactly the same
+  // dependency file as GCC (4.2), assuming the included files are the
+  // same.
+  const unsigned MaxColumns = 75;
+  unsigned Columns = 0;
+
+  for (std::vector<std::string>::iterator
+         I = Targets.begin(), E = Targets.end(); I != E; ++I) {
+    unsigned N = I->length();
+    if (Columns == 0) {
+      Columns += N;
+      *OS << *I;
+    } else if (Columns + N + 2 > MaxColumns) {
+      Columns = N + 2;
+      *OS << " \\\n  " << *I;
+    } else {
+      Columns += N + 1;
+      *OS << ' ' << *I;
+    }
+  }
+
+  *OS << ':';
+  Columns += 1;
+
+  // Now add each dependency in the order it was seen, but avoiding
+  // duplicates.
+  for (std::vector<std::string>::iterator I = Files.begin(),
+         E = Files.end(); I != E; ++I) {
+    // Start a new line if this would exceed the column limit. Make
+    // sure to leave space for a trailing " \" in case we need to
+    // break the line on the next iteration.
+    unsigned N = I->length();
+    if (Columns + (N + 1) + 2 > MaxColumns) {
+      *OS << " \\\n ";
+      Columns = 2;
+    }
+    *OS << ' ' << *I;
+    Columns += N + 1;
+  }
+  *OS << '\n';
+
+  // Create phony targets if requested.
+  if (PhonyTarget) {
+    // Skip the first entry, this is always the input file itself.
+    for (std::vector<std::string>::iterator I = Files.begin() + 1,
+           E = Files.end(); I != E; ++I) {
+      *OS << '\n';
+      *OS << *I << ":\n";
+    }
+  }
+}
+
diff --git a/lib/Frontend/DiagChecker.cpp b/lib/Frontend/DiagChecker.cpp
new file mode 100644
index 0000000..a50cc99
--- /dev/null
+++ b/lib/Frontend/DiagChecker.cpp
@@ -0,0 +1,301 @@
+//===--- DiagChecker.cpp - Diagnostic Checking Functions ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Process the input files and check that the diagnostic messages are expected.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Sema/ParseAST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+typedef TextDiagnosticBuffer::DiagList DiagList;
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+static void EmitError(Preprocessor &PP, SourceLocation Pos, const char *String){
+  unsigned ID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, String);
+  PP.Diag(Pos, ID);
+}
+
+
+// USING THE DIAGNOSTIC CHECKER:
+//
+// Indicating that a line expects an error or a warning is simple. Put a comment
+// on the line that has the diagnostic, use "expected-{error,warning}" to tag
+// if it's an expected error or warning, and place the expected text between {{
+// and }} markers. The full text doesn't have to be included, only enough to
+// ensure that the correct diagnostic was emitted.
+//
+// Here's an example:
+//
+//   int A = B; // expected-error {{use of undeclared identifier 'B'}}
+//
+// You can place as many diagnostics on one line as you wish. To make the code
+// more readable, you can use slash-newline to separate out the diagnostics.
+//
+// The simple syntax above allows each specification to match exactly one error.
+// You can use the extended syntax to customize this. The extended syntax is
+// "expected-<type> <n> {{diag text}}", where <type> is one of "error",
+// "warning" or "note", and <n> is a positive integer. This allows the
+// diagnostic to appear as many times as specified. Example:
+//
+//   void f(); // expected-note 2 {{previous declaration is here}}
+//
+
+/// FindDiagnostics - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in a diagnostic list.
+///
+static void FindDiagnostics(const char *CommentStart, unsigned CommentLen,
+                            DiagList &ExpectedDiags,
+                            Preprocessor &PP, SourceLocation Pos,
+                            const char *ExpectedStr) {
+  const char *CommentEnd = CommentStart+CommentLen;
+  unsigned ExpectedStrLen = strlen(ExpectedStr);
+
+  // Find all expected-foo diagnostics in the string and add them to
+  // ExpectedDiags.
+  while (CommentStart != CommentEnd) {
+    CommentStart = std::find(CommentStart, CommentEnd, 'e');
+    if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return;
+
+    // If this isn't expected-foo, ignore it.
+    if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) {
+      ++CommentStart;
+      continue;
+    }
+
+    CommentStart += ExpectedStrLen;
+
+    // Skip whitespace.
+    while (CommentStart != CommentEnd &&
+           isspace(CommentStart[0]))
+      ++CommentStart;
+
+    // Default, if we find the '{' now, is 1 time.
+    int Times = 1;
+    int Temp = 0;
+    // In extended syntax, there could be a digit now.
+    while (CommentStart != CommentEnd &&
+           CommentStart[0] >= '0' && CommentStart[0] <= '9') {
+      Temp *= 10;
+      Temp += CommentStart[0] - '0';
+      ++CommentStart;
+    }
+    if (Temp > 0)
+      Times = Temp;
+
+    // Skip whitespace again.
+    while (CommentStart != CommentEnd &&
+           isspace(CommentStart[0]))
+      ++CommentStart;
+
+    // We should have a {{ now.
+    if (CommentEnd-CommentStart < 2 ||
+        CommentStart[0] != '{' || CommentStart[1] != '{') {
+      if (std::find(CommentStart, CommentEnd, '{') != CommentEnd)
+        EmitError(PP, Pos, "bogus characters before '{{' in expected string");
+      else
+        EmitError(PP, Pos, "cannot find start ('{{') of expected string");
+      return;
+    }
+    CommentStart += 2;
+
+    // Find the }}.
+    const char *ExpectedEnd = CommentStart;
+    while (1) {
+      ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}');
+      if (CommentEnd-ExpectedEnd < 2) {
+        EmitError(PP, Pos, "cannot find end ('}}') of expected string");
+        return;
+      }
+
+      if (ExpectedEnd[1] == '}')
+        break;
+
+      ++ExpectedEnd;  // Skip over singular }'s
+    }
+
+    std::string Msg(CommentStart, ExpectedEnd);
+    std::string::size_type FindPos;
+    while ((FindPos = Msg.find("\\n")) != std::string::npos)
+      Msg.replace(FindPos, 2, "\n");
+    // Add is possibly multiple times.
+    for (int i = 0; i < Times; ++i)
+      ExpectedDiags.push_back(std::make_pair(Pos, Msg));
+
+    CommentStart = ExpectedEnd;
+  }
+}
+
+/// FindExpectedDiags - Lex the main source file to find all of the
+//   expected errors and warnings.
+static void FindExpectedDiags(Preprocessor &PP,
+                              DiagList &ExpectedErrors,
+                              DiagList &ExpectedWarnings,
+                              DiagList &ExpectedNotes) {
+  // Create a raw lexer to pull all the comments out of the main file.  We don't
+  // want to look in #include'd headers for expected-error strings.
+  FileID FID = PP.getSourceManager().getMainFileID();
+
+  // Create a lexer to lex all the tokens of the main file in raw mode.
+  const llvm::MemoryBuffer *FromFile = PP.getSourceManager().getBuffer(FID);
+  Lexer RawLex(FID, FromFile, PP.getSourceManager(), PP.getLangOptions());
+
+  // Return comments as tokens, this is how we find expected diagnostics.
+  RawLex.SetCommentRetentionState(true);
+
+  Token Tok;
+  Tok.setKind(tok::comment);
+  while (Tok.isNot(tok::eof)) {
+    RawLex.Lex(Tok);
+    if (!Tok.is(tok::comment)) continue;
+
+    std::string Comment = PP.getSpelling(Tok);
+    if (Comment.empty()) continue;
+
+
+    // Find all expected errors.
+    FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP,
+                    Tok.getLocation(), "expected-error");
+
+    // Find all expected warnings.
+    FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP,
+                    Tok.getLocation(), "expected-warning");
+
+    // Find all expected notes.
+    FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP,
+                    Tok.getLocation(), "expected-note");
+  };
+}
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+///
+static bool PrintProblem(SourceManager &SourceMgr,
+                         const_diag_iterator diag_begin,
+                         const_diag_iterator diag_end,
+                         const char *Msg) {
+  if (diag_begin == diag_end) return false;
+
+  llvm::errs() << Msg << "\n";
+  for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I)
+    llvm::errs() << "  Line " << SourceMgr.getInstantiationLineNumber(I->first)
+                 << " " << I->second << "\n";
+
+  return true;
+}
+
+/// CompareDiagLists - Compare two diagnostic lists and return the difference
+/// between them.
+///
+static bool CompareDiagLists(SourceManager &SourceMgr,
+                             const_diag_iterator d1_begin,
+                             const_diag_iterator d1_end,
+                             const_diag_iterator d2_begin,
+                             const_diag_iterator d2_end,
+                             const char *MsgLeftOnly,
+                             const char *MsgRightOnly) {
+  DiagList LeftOnly;
+  DiagList Left(d1_begin, d1_end);
+  DiagList Right(d2_begin, d2_end);
+
+  for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
+    unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first);
+    const std::string &Diag1 = I->second;
+
+    DiagList::iterator II, IE;
+    for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
+      unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+      if (LineNo1 != LineNo2) continue;
+
+      const std::string &Diag2 = II->second;
+      if (Diag2.find(Diag1) != std::string::npos ||
+          Diag1.find(Diag2) != std::string::npos) {
+        break;
+      }
+    }
+    if (II == IE) {
+      // Not found.
+      LeftOnly.push_back(*I);
+    } else {
+      // Found. The same cannot be found twice.
+      Right.erase(II);
+    }
+  }
+  // Now all that's left in Right are those that were not matched.
+
+  return PrintProblem(SourceMgr, LeftOnly.begin(), LeftOnly.end(), MsgLeftOnly)
+       | PrintProblem(SourceMgr, Right.begin(), Right.end(), MsgRightOnly);
+}
+
+/// CheckResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+///
+static bool CheckResults(Preprocessor &PP,
+                         const DiagList &ExpectedErrors,
+                         const DiagList &ExpectedWarnings,
+                         const DiagList &ExpectedNotes) {
+  const DiagnosticClient *DiagClient = PP.getDiagnostics().getClient();
+  assert(DiagClient != 0 &&
+      "DiagChecker requires a valid TextDiagnosticBuffer");
+  const TextDiagnosticBuffer &Diags =
+    static_cast<const TextDiagnosticBuffer&>(*DiagClient);
+  SourceManager &SourceMgr = PP.getSourceManager();
+
+  // We want to capture the delta between what was expected and what was
+  // seen.
+  //
+  //   Expected \ Seen - set expected but not seen
+  //   Seen \ Expected - set seen but not expected
+  bool HadProblem = false;
+
+  // See if there are error mismatches.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 ExpectedErrors.begin(), ExpectedErrors.end(),
+                                 Diags.err_begin(), Diags.err_end(),
+                                 "Errors expected but not seen:",
+                                 "Errors seen but not expected:");
+
+  // See if there are warning mismatches.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 ExpectedWarnings.begin(),
+                                 ExpectedWarnings.end(),
+                                 Diags.warn_begin(), Diags.warn_end(),
+                                 "Warnings expected but not seen:",
+                                 "Warnings seen but not expected:");
+
+  // See if there are note mismatches.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 ExpectedNotes.begin(),
+                                 ExpectedNotes.end(),
+                                 Diags.note_begin(), Diags.note_end(),
+                                 "Notes expected but not seen:",
+                                 "Notes seen but not expected:");
+
+  return HadProblem;
+}
+
+
+/// CheckDiagnostics - Gather the expected diagnostics and check them.
+bool clang::CheckDiagnostics(Preprocessor &PP) {
+  // Gather the set of expected diagnostics.
+  DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes;
+  FindExpectedDiags(PP, ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+
+  // Check that the expected diagnostics occurred.
+  return CheckResults(PP, ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+}
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
new file mode 100644
index 0000000..0263c30
--- /dev/null
+++ b/lib/Frontend/DocumentXML.cpp
@@ -0,0 +1,338 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringExtras.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
+  Out(out),
+  Ctx(0),
+  HasCurrentNodeSubNodes(false) {
+  NodeStack.push(rootName);
+  Out << "<?xml version=\"1.0\"?>\n<" << rootName;
+}
+
+//---------------------------------------------------------
+DocumentXML& DocumentXML::addSubNode(const std::string& name) {
+  if (!HasCurrentNodeSubNodes)
+    Out << ">\n";
+  NodeStack.push(name);
+  HasCurrentNodeSubNodes = false;
+  Indent();
+  Out << "<" << NodeStack.top();
+  return *this;
+}
+
+//---------------------------------------------------------
+void DocumentXML::Indent() {
+  for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
+    Out << ' ';
+}
+
+//---------------------------------------------------------
+DocumentXML& DocumentXML::toParent() {
+  assert(NodeStack.size() > 1 && "too much backtracking");
+
+  if (HasCurrentNodeSubNodes) {
+    Indent();
+    Out << "</" << NodeStack.top() << ">\n";
+  } else
+    Out << "/>\n";
+  NodeStack.pop();
+  HasCurrentNodeSubNodes = true;
+  return *this;
+}
+
+//---------------------------------------------------------
+namespace {
+
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
+
+unsigned getNewId(tIdType idType) {
+  static unsigned int idCounts[ID_LAST] = { 0 };
+  return ++idCounts[idType];
+}
+
+//---------------------------------------------------------
+inline std::string getPrefixedId(unsigned uId, tIdType idType) {
+  static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
+  char buffer[20];
+  char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
+  *--BufPtr = idPrefix[idType];
+  return BufPtr;
+}
+
+//---------------------------------------------------------
+template<class T, class V>
+bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) {
+  typename T::iterator i = idMap.find(value);
+  bool toAdd = i == idMap.end();
+  if (toAdd)
+    idMap.insert(typename T::value_type(value, getNewId(idType)));
+  return toAdd;
+}
+
+} // anon NS
+
+
+//---------------------------------------------------------
+std::string DocumentXML::escapeString(const char* pStr,
+                                      std::string::size_type len) {
+  std::string value;
+  value.reserve(len + 1);
+  char buffer[16];
+  for (unsigned i = 0; i < len; ++i) {
+    switch (char C = pStr[i]) {
+    default:
+      if (isprint(C))
+        value += C;
+      else {
+        sprintf(buffer, "\\%03o", C);
+        value += buffer;
+      }
+      break;
+
+    case '\n': value += "\\n"; break;
+    case '\t': value += "\\t"; break;
+    case '\a': value += "\\a"; break;
+    case '\b': value += "\\b"; break;
+    case '\r': value += "\\r"; break;
+
+    case '&': value += "&amp;"; break;
+    case '<': value += "&lt;"; break;
+    case '>': value += "&gt;"; break;
+    case '"': value += "&quot;"; break;
+    case '\'':  value += "&apos;"; break;
+
+    }
+  }
+  return value;
+}
+
+//---------------------------------------------------------
+void DocumentXML::finalize() {
+  assert(NodeStack.size() == 1 && "not completely backtracked");
+
+  addSubNode("ReferenceSection");
+  addSubNode("Types");
+
+  for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
+       i != e; ++i) {
+    if (i->first.hasLocalQualifiers()) {
+      writeTypeToXML(i->first);
+      addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+      toParent();
+    }
+  }
+
+  for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(),
+         e = BasicTypes.end(); i != e; ++i) {
+    writeTypeToXML(i->first);
+    addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+    toParent();
+  }
+
+
+  toParent().addSubNode("Contexts");
+
+  for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(),
+         e = Contexts.end(); i != e; ++i) {
+    addSubNode(i->first->getDeclKindName());
+    addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+    if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first))
+      addAttribute("name", ND->getNameAsString());
+    if (const TagDecl *TD = dyn_cast<TagDecl>(i->first))
+      addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL));
+    else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first))
+      addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs<FunctionType>()], ID_NORMAL));
+
+    if (const DeclContext* parent = i->first->getParent())
+      addAttribute("context", parent);
+    toParent();
+  }
+
+  toParent().addSubNode("Files");
+
+  for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(),
+         e = SourceFiles.end(); i != e; ++i) {
+    addSubNode("File");
+    addAttribute("id", getPrefixedId(i->second, ID_FILE));
+    addAttribute("name", escapeString(i->first.c_str(), i->first.size()));
+    toParent();
+  }
+
+  toParent().toParent();
+
+  // write the root closing node (which has always subnodes)
+  Out << "</" << NodeStack.top() << ">\n";
+}
+
+//---------------------------------------------------------
+void DocumentXML::addAttribute(const char* pAttributeName,
+                               const QualType& pType) {
+  addTypeRecursively(pType);
+  addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName,
+                                  const Type* pType) {
+  addTypeRecursively(pType);
+  addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addTypeRecursively(const QualType& pType)
+{
+  if (addToMap(Types, pType))
+  {
+    addTypeRecursively(pType.getTypePtr());
+    // beautifier: a non-qualified type shall be transparent
+    if (!pType.hasLocalQualifiers())
+    {
+      Types[pType] = BasicTypes[pType.getTypePtr()];
+    }
+  }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addTypeRecursively(const Type* pType)
+{
+  if (addToMap(BasicTypes, pType))
+  {
+    addParentTypes(pType);
+/*
+    // FIXME: doesn't work in the immediate streaming approach
+    if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
+    {
+      addSubNode("VariableArraySizeExpression");
+      PrintStmt(VAT->getSizeExpr());
+      toParent();
+    }
+*/
+  }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
+{
+  addContextsRecursively(DC);
+  addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+  if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+  {
+    addContextsRecursively(DC);
+    addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+  }
+  else
+  {
+    addToMap(Decls, D);
+    addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+  }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+  addPtrAttribute(pName, static_cast<const DeclContext*>(D));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addContextsRecursively(const DeclContext *DC)
+{
+  if (DC != 0 && addToMap(Contexts, DC))
+  {
+    addContextsRecursively(DC->getParent());
+  }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addSourceFileAttribute(const std::string& fileName)
+{
+  addToMap(SourceFiles, fileName, ID_FILE);
+  addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
+}
+
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+  addToMap(Labels, L, ID_LABEL);
+  addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
+//---------------------------------------------------------
+PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
+{
+  SourceManager& SM = Ctx->getSourceManager();
+  SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+  PresumedLoc PLoc;
+  if (!SpellingLoc.isInvalid())
+  {
+    PLoc = SM.getPresumedLoc(SpellingLoc);
+    addSourceFileAttribute(PLoc.getFilename());
+    addAttribute("line", PLoc.getLine());
+    addAttribute("col", PLoc.getColumn());
+  }
+  // else there is no error in some cases (eg. CXXThisExpr)
+  return PLoc;
+}
+
+//---------------------------------------------------------
+void DocumentXML::addLocationRange(const SourceRange& R)
+{
+  PresumedLoc PStartLoc = addLocation(R.getBegin());
+  if (R.getBegin() != R.getEnd())
+  {
+    SourceManager& SM = Ctx->getSourceManager();
+    SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd());
+    if (!SpellingLoc.isInvalid())
+    {
+      PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc);
+      if (PStartLoc.isInvalid() ||
+          strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) {
+        addToMap(SourceFiles, PLoc.getFilename(), ID_FILE);
+        addAttribute("endfile", PLoc.getFilename());
+        addAttribute("endline", PLoc.getLine());
+        addAttribute("endcol", PLoc.getColumn());
+      } else if (PLoc.getLine() != PStartLoc.getLine()) {
+        addAttribute("endline", PLoc.getLine());
+        addAttribute("endcol", PLoc.getColumn());
+      } else {
+        addAttribute("endcol", PLoc.getColumn());
+      }
+    }
+  }
+}
+
+//---------------------------------------------------------
+void DocumentXML::PrintDecl(Decl *D)
+{
+  writeDeclToXML(D);
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/FixItRewriter.cpp b/lib/Frontend/FixItRewriter.cpp
new file mode 100644
index 0000000..0b04cf2
--- /dev/null
+++ b/lib/Frontend/FixItRewriter.cpp
@@ -0,0 +1,198 @@
+//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a diagnostic client adaptor that performs rewrites as
+// suggested by code modification hints attached to diagnostics. It
+// then forwards any diagnostics to the adapted diagnostic client.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FixItRewriter.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <cstdio>
+
+using namespace clang;
+
+FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
+                             const LangOptions &LangOpts)
+  : Diags(Diags), Rewrite(SourceMgr, LangOpts), NumFailures(0) {
+  Client = Diags.getClient();
+  Diags.setClient(this);
+}
+
+FixItRewriter::~FixItRewriter() {
+  Diags.setClient(Client);
+}
+
+bool FixItRewriter::WriteFixedFile(const std::string &InFileName,
+                                   const std::string &OutFileName) {
+  if (NumFailures > 0) {
+    Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
+    return true;
+  }
+
+  llvm::OwningPtr<llvm::raw_ostream> OwnedStream;
+  llvm::raw_ostream *OutFile;
+  if (!OutFileName.empty()) {
+    std::string Err;
+    OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), Err,
+                                       llvm::raw_fd_ostream::F_Binary);
+    OwnedStream.reset(OutFile);
+  } else if (InFileName == "-") {
+    OutFile = &llvm::outs();
+  } else {
+    llvm::sys::Path Path(InFileName);
+    std::string Suffix = Path.getSuffix();
+    Path.eraseSuffix();
+    Path.appendSuffix("fixit." + Suffix);
+    std::string Err;
+    OutFile = new llvm::raw_fd_ostream(Path.c_str(), Err,
+                                       llvm::raw_fd_ostream::F_Binary);
+    OwnedStream.reset(OutFile);
+  }
+
+  FileID MainFileID = Rewrite.getSourceMgr().getMainFileID();
+  if (const RewriteBuffer *RewriteBuf =
+        Rewrite.getRewriteBufferFor(MainFileID)) {
+    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
+  } else {
+    Diag(FullSourceLoc(), diag::note_fixit_main_file_unchanged);
+  }
+  OutFile->flush();
+
+  return false;
+}
+
+bool FixItRewriter::IncludeInDiagnosticCounts() const {
+  return Client? Client->IncludeInDiagnosticCounts() : true;
+}
+
+void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                     const DiagnosticInfo &Info) {
+  Client->HandleDiagnostic(DiagLevel, Info);
+
+  // Skip over any diagnostics that are ignored.
+  if (DiagLevel == Diagnostic::Ignored)
+    return;
+
+  if (!FixItLocations.empty()) {
+    // The user has specified the locations where we should perform
+    // the various fix-it modifications.
+
+    // If this diagnostic does not have any code modifications,
+    // completely ignore it, even if it's an error: fix-it locations
+    // are meant to perform specific fix-ups even in the presence of
+    // other errors.
+    if (Info.getNumCodeModificationHints() == 0)
+      return;
+
+    // See if the location of the error is one that matches what the
+    // user requested.
+    bool AcceptableLocation = false;
+    const FileEntry *File
+      = Rewrite.getSourceMgr().getFileEntryForID(
+                                            Info.getLocation().getFileID());
+    unsigned Line = Info.getLocation().getSpellingLineNumber();
+    unsigned Column = Info.getLocation().getSpellingColumnNumber();
+    for (llvm::SmallVector<RequestedSourceLocation, 4>::iterator
+           Loc = FixItLocations.begin(), LocEnd = FixItLocations.end();
+         Loc != LocEnd; ++Loc) {
+      if (Loc->File == File && Loc->Line == Line && Loc->Column == Column) {
+        AcceptableLocation = true;
+        break;
+      }
+    }
+
+    if (!AcceptableLocation)
+      return;
+  } else if (DiagLevel == Diagnostic::Note) {
+    // Don't apply fix-it modifications in notes.
+    return;
+  }
+
+  // Make sure that we can perform all of the modifications we
+  // in this diagnostic.
+  bool CanRewrite = Info.getNumCodeModificationHints() > 0;
+  for (unsigned Idx = 0, Last = Info.getNumCodeModificationHints();
+       Idx < Last; ++Idx) {
+    const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx);
+    if (Hint.RemoveRange.isValid() &&
+        Rewrite.getRangeSize(Hint.RemoveRange) == -1) {
+      CanRewrite = false;
+      break;
+    }
+
+    if (Hint.InsertionLoc.isValid() &&
+        !Rewrite.isRewritable(Hint.InsertionLoc)) {
+      CanRewrite = false;
+      break;
+    }
+  }
+
+  if (!CanRewrite) {
+    if (Info.getNumCodeModificationHints() > 0)
+      Diag(Info.getLocation(), diag::note_fixit_in_macro);
+
+    // If this was an error, refuse to perform any rewriting.
+    if (DiagLevel == Diagnostic::Error || DiagLevel == Diagnostic::Fatal) {
+      if (++NumFailures == 1)
+        Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
+    }
+    return;
+  }
+
+  bool Failed = false;
+  for (unsigned Idx = 0, Last = Info.getNumCodeModificationHints();
+       Idx < Last; ++Idx) {
+    const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx);
+    if (!Hint.RemoveRange.isValid()) {
+      // We're adding code.
+      if (Rewrite.InsertTextBefore(Hint.InsertionLoc, Hint.CodeToInsert))
+        Failed = true;
+      continue;
+    }
+
+    if (Hint.CodeToInsert.empty()) {
+      // We're removing code.
+      if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
+                             Rewrite.getRangeSize(Hint.RemoveRange)))
+        Failed = true;
+      continue;
+    }
+
+    // We're replacing code.
+    if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(),
+                            Rewrite.getRangeSize(Hint.RemoveRange),
+                            Hint.CodeToInsert))
+      Failed = true;
+  }
+
+  if (Failed) {
+    ++NumFailures;
+    Diag(Info.getLocation(), diag::note_fixit_failed);
+    return;
+  }
+
+  Diag(Info.getLocation(), diag::note_fixit_applied);
+}
+
+/// \brief Emit a diagnostic via the adapted diagnostic client.
+void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
+  // When producing this diagnostic, we temporarily bypass ourselves,
+  // clear out any current diagnostic, and let the downstream client
+  // format the diagnostic.
+  Diags.setClient(Client);
+  Diags.Clear();
+  Diags.Report(Loc, DiagID);
+  Diags.setClient(this);
+}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
new file mode 100644
index 0000000..96a68c9
--- /dev/null
+++ b/lib/Frontend/FrontendAction.cpp
@@ -0,0 +1,226 @@
+//===--- FrontendAction.cpp -----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Sema/ParseAST.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+FrontendAction::FrontendAction() : Instance(0) {}
+
+FrontendAction::~FrontendAction() {}
+
+void FrontendAction::setCurrentFile(llvm::StringRef Value, ASTUnit *AST) {
+  CurrentFile = Value;
+  CurrentASTUnit.reset(AST);
+}
+
+bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
+                                     llvm::StringRef Filename,
+                                     bool IsAST) {
+  assert(!Instance && "Already processing a source file!");
+  assert(!Filename.empty() && "Unexpected empty filename!");
+  setCurrentFile(Filename);
+  setCompilerInstance(&CI);
+
+  // AST files follow a very different path, since they share objects via the
+  // AST unit.
+  if (IsAST) {
+    assert(!usesPreprocessorOnly() &&
+           "Attempt to pass AST file to preprocessor only action!");
+    assert(hasASTSupport() && "This action does not have AST support!");
+
+    std::string Error;
+    ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, CI.getDiagnostics());
+    if (!AST)
+      goto failure;
+
+    setCurrentFile(Filename, AST);
+
+    // Set the shared objects, these are reset when we finish processing the
+    // file, otherwise the CompilerInstance will happily destroy them.
+    CI.setFileManager(&AST->getFileManager());
+    CI.setSourceManager(&AST->getSourceManager());
+    CI.setPreprocessor(&AST->getPreprocessor());
+    CI.setASTContext(&AST->getASTContext());
+
+    // Initialize the action.
+    if (!BeginSourceFileAction(CI, Filename))
+      goto failure;
+
+    /// Create the AST consumer.
+    CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+    if (!CI.hasASTConsumer())
+      goto failure;
+
+    return true;
+  }
+
+  // Inform the diagnostic client we are processing a source file.
+  CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
+                                           &CI.getPreprocessor());
+
+  // Initialize the action.
+  if (!BeginSourceFileAction(CI, Filename))
+    goto failure;
+
+  /// Create the AST context and consumer unless this is a preprocessor only
+  /// action.
+  if (!usesPreprocessorOnly()) {
+    CI.createASTContext();
+    CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+    if (!CI.hasASTConsumer())
+      goto failure;
+
+    /// Use PCH?
+    if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
+      assert(hasPCHSupport() && "This action does not have PCH support!");
+      CI.createPCHExternalASTSource(
+        CI.getPreprocessorOpts().ImplicitPCHInclude);
+      if (!CI.getASTContext().getExternalSource())
+        goto failure;
+    }
+  }
+
+  // Initialize builtin info as long as we aren't using an external AST
+  // source.
+  if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
+    Preprocessor &PP = CI.getPreprocessor();
+    PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
+                                           PP.getLangOptions().NoBuiltin);
+  }
+
+  return true;
+
+  // If we failed, reset state since the client will not end up calling the
+  // matching EndSourceFile().
+  failure:
+  if (isCurrentFileAST()) {
+    CI.takeASTContext();
+    CI.takePreprocessor();
+    CI.takeSourceManager();
+    CI.takeFileManager();
+  }
+
+  CI.getDiagnosticClient().EndSourceFile();
+  setCurrentFile("");
+  setCompilerInstance(0);
+  return false;
+}
+
+void FrontendAction::Execute() {
+  CompilerInstance &CI = getCompilerInstance();
+
+  // Initialize the main file entry. This needs to be delayed until after PCH
+  // has loaded.
+  if (isCurrentFileAST()) {
+    // Set the main file ID to an empty file.
+    //
+    // FIXME: We probably shouldn't need this, but for now this is the
+    // simplest way to reuse the logic in ParseAST.
+    const char *EmptyStr = "";
+    llvm::MemoryBuffer *SB =
+      llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
+    CI.getSourceManager().createMainFileIDForMemBuffer(SB);
+  } else {
+    if (!CI.InitializeSourceManager(getCurrentFile()))
+      return;
+  }
+
+  if (CI.hasFrontendTimer()) {
+    llvm::TimeRegion Timer(CI.getFrontendTimer());
+    ExecuteAction();
+  }
+  else ExecuteAction();
+}
+
+void FrontendAction::EndSourceFile() {
+  CompilerInstance &CI = getCompilerInstance();
+
+  // Finalize the action.
+  EndSourceFileAction();
+
+  // Release the consumer and the AST, in that order since the consumer may
+  // perform actions in its destructor which require the context.
+  //
+  // FIXME: There is more per-file stuff we could just drop here?
+  if (CI.getFrontendOpts().DisableFree) {
+    CI.takeASTConsumer();
+    if (!isCurrentFileAST())
+      CI.takeASTContext();
+  } else {
+    CI.setASTConsumer(0);
+    if (!isCurrentFileAST())
+      CI.setASTContext(0);
+  }
+
+  if (CI.getFrontendOpts().ShowStats) {
+    llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
+    CI.getPreprocessor().PrintStats();
+    CI.getPreprocessor().getIdentifierTable().PrintStats();
+    CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
+    CI.getSourceManager().PrintStats();
+    llvm::errs() << "\n";
+  }
+
+  // Cleanup the output streams, and erase the output files if we encountered
+  // an error.
+  CI.ClearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors());
+
+  // Inform the diagnostic client we are done with this source file.
+  CI.getDiagnosticClient().EndSourceFile();
+
+  if (isCurrentFileAST()) {
+    CI.takeASTContext();
+    CI.takePreprocessor();
+    CI.takeSourceManager();
+    CI.takeFileManager();
+  }
+
+  setCompilerInstance(0);
+  setCurrentFile("");
+}
+
+//===----------------------------------------------------------------------===//
+// Utility Actions
+//===----------------------------------------------------------------------===//
+
+void ASTFrontendAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+
+  // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+  // here so the source manager would be initialized.
+  if (hasCodeCompletionSupport() &&
+      !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+    CI.createCodeCompletionConsumer();
+
+  // Use a code completion consumer?
+  CodeCompleteConsumer *CompletionConsumer = 0;
+  if (CI.hasCodeCompletionConsumer())
+    CompletionConsumer = &CI.getCodeCompletionConsumer();
+
+  ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(),
+           CI.getFrontendOpts().ShowStats,
+           usesCompleteTranslationUnit(), CompletionConsumer);
+}
+
+ASTConsumer *
+PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+                                              llvm::StringRef InFile) {
+  llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
+}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
new file mode 100644
index 0000000..1c958a7
--- /dev/null
+++ b/lib/Frontend/FrontendActions.cpp
@@ -0,0 +1,311 @@
+//===--- FrontendActions.cpp ----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FixItRewriter.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
+                                               llvm::StringRef InFile) {
+  return CreateAnalysisConsumer(CI.getPreprocessor(),
+                                CI.getFrontendOpts().OutputFile,
+                                CI.getAnalyzerOpts());
+}
+
+ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
+                                               llvm::StringRef InFile) {
+  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
+    return CreateASTPrinter(OS);
+  return 0;
+}
+
+ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
+                                                  llvm::StringRef InFile) {
+  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
+    return CreateASTPrinterXML(OS);
+  return 0;
+}
+
+ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
+                                              llvm::StringRef InFile) {
+  return CreateASTDumper();
+}
+
+ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
+                                              llvm::StringRef InFile) {
+  return CreateASTViewer();
+}
+
+ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
+                                                       llvm::StringRef InFile) {
+  return CreateDeclContextPrinter();
+}
+
+ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI,
+                                                 llvm::StringRef InFile) {
+  return CreateRecordLayoutDumper();
+}
+
+ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
+                                                  llvm::StringRef InFile) {
+  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
+  if (CI.getFrontendOpts().RelocatablePCH &&
+      Sysroot.empty()) {
+    CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
+    return 0;
+  }
+
+  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
+  if (!OS)
+    return 0;
+
+  if (CI.getFrontendOpts().RelocatablePCH)
+    return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
+
+  return CreatePCHGenerator(CI.getPreprocessor(), OS);
+}
+
+ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
+                                                llvm::StringRef InFile) {
+  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
+    return CreateHTMLPrinter(OS, CI.getPreprocessor());
+  return 0;
+}
+
+ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
+                                                      llvm::StringRef InFile) {
+  return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
+}
+
+FixItAction::FixItAction() {}
+FixItAction::~FixItAction() {}
+
+ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
+                                            llvm::StringRef InFile) {
+  return new ASTConsumer();
+}
+
+/// AddFixItLocations - Add any individual user specified "fix-it" locations,
+/// and return true on success.
+static bool AddFixItLocations(CompilerInstance &CI,
+                              FixItRewriter &FixItRewrite) {
+  const std::vector<ParsedSourceLocation> &Locs =
+    CI.getFrontendOpts().FixItLocations;
+  for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
+    const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
+    if (!File) {
+      CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
+        << Locs[i].FileName;
+      return false;
+    }
+
+    RequestedSourceLocation Requested;
+    Requested.File = File;
+    Requested.Line = Locs[i].Line;
+    Requested.Column = Locs[i].Column;
+    FixItRewrite.addFixItLocation(Requested);
+  }
+
+  return true;
+}
+
+bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
+                                        llvm::StringRef Filename) {
+  Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
+                                   CI.getLangOpts()));
+  if (!AddFixItLocations(CI, *Rewriter))
+    return false;
+
+  return true;
+}
+
+void FixItAction::EndSourceFileAction() {
+  const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
+  Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile);
+}
+
+ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
+                                                  llvm::StringRef InFile) {
+  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
+    return CreateObjCRewriter(InFile, OS,
+                              CI.getDiagnostics(), CI.getLangOpts(),
+                              CI.getDiagnosticOpts().NoRewriteMacros);
+  return 0;
+}
+
+ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
+                                                 llvm::StringRef InFile) {
+  return new ASTConsumer();
+}
+
+CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {}
+
+ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
+                                              llvm::StringRef InFile) {
+  BackendAction BA = static_cast<BackendAction>(Act);
+  llvm::OwningPtr<llvm::raw_ostream> OS;
+  switch (BA) {
+  case Backend_EmitAssembly:
+    OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
+    break;
+  case Backend_EmitLL:
+    OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
+    break;
+  case Backend_EmitBC:
+    OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
+    break;
+  case Backend_EmitNothing:
+    break;
+  case Backend_EmitObj:
+    OS.reset(CI.createDefaultOutputFile(true, InFile, "o"));
+    break;
+  }
+  if (BA != Backend_EmitNothing && !OS)
+    return 0;
+
+  return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
+                               CI.getCodeGenOpts(), CI.getTargetOpts(),
+                               CI.getFrontendOpts().ShowTimers, InFile,
+                               OS.take(), CI.getLLVMContext());
+}
+
+EmitAssemblyAction::EmitAssemblyAction()
+  : CodeGenAction(Backend_EmitAssembly) {}
+
+EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {}
+
+EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {}
+
+EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {}
+
+EmitObjAction::EmitObjAction() : CodeGenAction(Backend_EmitObj) {}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+void DumpRawTokensAction::ExecuteAction() {
+  Preprocessor &PP = getCompilerInstance().getPreprocessor();
+  SourceManager &SM = PP.getSourceManager();
+
+  // Start lexing the specified input file.
+  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
+  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
+  RawLex.SetKeepWhitespaceMode(true);
+
+  Token RawTok;
+  RawLex.LexFromRawLexer(RawTok);
+  while (RawTok.isNot(tok::eof)) {
+    PP.DumpToken(RawTok, true);
+    llvm::errs() << "\n";
+    RawLex.LexFromRawLexer(RawTok);
+  }
+}
+
+void DumpTokensAction::ExecuteAction() {
+  Preprocessor &PP = getCompilerInstance().getPreprocessor();
+  // Start preprocessing the specified input file.
+  Token Tok;
+  PP.EnterMainSourceFile();
+  do {
+    PP.Lex(Tok);
+    PP.DumpToken(Tok, true);
+    llvm::errs() << "\n";
+  } while (Tok.isNot(tok::eof));
+}
+
+void GeneratePTHAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+  if (CI.getFrontendOpts().OutputFile.empty() ||
+      CI.getFrontendOpts().OutputFile == "-") {
+    // FIXME: Don't fail this way.
+    // FIXME: Verify that we can actually seek in the given file.
+    llvm::llvm_report_error("PTH requires a seekable file for output!");
+  }
+  llvm::raw_fd_ostream *OS =
+    CI.createDefaultOutputFile(true, getCurrentFile());
+  if (!OS) return;
+
+  CacheTokens(CI.getPreprocessor(), OS);
+}
+
+void ParseOnlyAction::ExecuteAction() {
+  Preprocessor &PP = getCompilerInstance().getPreprocessor();
+  llvm::OwningPtr<Action> PA(new MinimalAction(PP));
+
+  Parser P(PP, *PA);
+  PP.EnterMainSourceFile();
+  P.ParseTranslationUnit();
+}
+
+void PreprocessOnlyAction::ExecuteAction() {
+  Preprocessor &PP = getCompilerInstance().getPreprocessor();
+
+  Token Tok;
+  // Start parsing the specified input file.
+  PP.EnterMainSourceFile();
+  do {
+    PP.Lex(Tok);
+  } while (Tok.isNot(tok::eof));
+}
+
+void PrintParseAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+  Preprocessor &PP = getCompilerInstance().getPreprocessor();
+  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+  if (!OS) return;
+
+  llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
+
+  Parser P(PP, *PA);
+  PP.EnterMainSourceFile();
+  P.ParseTranslationUnit();
+}
+
+void PrintPreprocessedAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+  // Output file needs to be set to 'Binary', to avoid converting Unix style
+  // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
+  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+  if (!OS) return;
+
+  DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
+                           CI.getPreprocessorOutputOpts());
+}
+
+void RewriteMacrosAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+  if (!OS) return;
+
+  RewriteMacrosInInput(CI.getPreprocessor(), OS);
+}
+
+void RewriteTestAction::ExecuteAction() {
+  CompilerInstance &CI = getCompilerInstance();
+  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+  if (!OS) return;
+
+  DoRewriteTest(CI.getPreprocessor(), OS);
+}
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
new file mode 100644
index 0000000..bd91638
--- /dev/null
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -0,0 +1,31 @@
+//===--- FrontendOptions.cpp ----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+FrontendOptions::InputKind
+FrontendOptions::getInputKindForExtension(llvm::StringRef Extension) {
+  return llvm::StringSwitch<InputKind>(Extension)
+    .Case("ast", IK_AST)
+    .Case("c", IK_C)
+    .Cases("S", "s", IK_Asm)
+    .Case("i", IK_PreprocessedC)
+    .Case("ii", IK_PreprocessedCXX)
+    .Case("m", IK_ObjC)
+    .Case("mi", IK_PreprocessedObjC)
+    .Cases("mm", "M", IK_ObjCXX)
+    .Case("mii", IK_PreprocessedObjCXX)
+    .Case("C", IK_CXX)
+    .Cases("C", "cc", "cp", IK_CXX)
+    .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX)
+    .Case("cl", IK_OpenCL)
+    .Default(IK_C);
+}
diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp
new file mode 100644
index 0000000..6251bac
--- /dev/null
+++ b/lib/Frontend/GeneratePCH.cpp
@@ -0,0 +1,80 @@
+//===--- GeneratePCH.cpp - AST Consumer for PCH Generation ------*- 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 CreatePCHGenerate function, which creates an
+//  ASTConsume that generates a PCH file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/PCHWriter.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/FileManager.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace clang;
+
+namespace {
+  class PCHGenerator : public SemaConsumer {
+    const Preprocessor &PP;
+    const char *isysroot;
+    llvm::raw_ostream *Out;
+    Sema *SemaPtr;
+    MemorizeStatCalls *StatCalls; // owned by the FileManager
+
+  public:
+    explicit PCHGenerator(const Preprocessor &PP,
+                          const char *isysroot,
+                          llvm::raw_ostream *Out);
+    virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
+    virtual void HandleTranslationUnit(ASTContext &Ctx);
+  };
+}
+
+PCHGenerator::PCHGenerator(const Preprocessor &PP,
+                           const char *isysroot,
+                           llvm::raw_ostream *OS)
+  : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0) {
+
+  // Install a stat() listener to keep track of all of the stat()
+  // calls.
+  StatCalls = new MemorizeStatCalls;
+  PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true);
+}
+
+void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
+  if (PP.getDiagnostics().hasErrorOccurred())
+    return;
+
+  // Write the PCH contents into a buffer
+  std::vector<unsigned char> Buffer;
+  llvm::BitstreamWriter Stream(Buffer);
+  PCHWriter Writer(Stream);
+
+  // Emit the PCH file
+  assert(SemaPtr && "No Sema?");
+  Writer.WritePCH(*SemaPtr, StatCalls, isysroot);
+
+  // Write the generated bitstream to "Out".
+  Out->write((char *)&Buffer.front(), Buffer.size());
+
+  // Make sure it hits disk now.
+  Out->flush();
+}
+
+ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
+                                       llvm::raw_ostream *OS,
+                                       const char *isysroot) {
+  return new PCHGenerator(PP, isysroot, OS);
+}
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp
new file mode 100644
index 0000000..f695254
--- /dev/null
+++ b/lib/Frontend/HTMLDiagnostics.cpp
@@ -0,0 +1,584 @@
+//===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- 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 HTMLDiagnostics object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Checker/BugReporter/PathDiagnostic.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Boilerplate.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class HTMLDiagnostics : public PathDiagnosticClient {
+  llvm::sys::Path Directory, FilePrefix;
+  bool createdDir, noDir;
+  const Preprocessor &PP;
+  std::vector<const PathDiagnostic*> BatchedDiags;
+public:
+  HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
+  
+  virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
+  
+  virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
+
+  virtual void HandlePathDiagnostic(const PathDiagnostic* D);
+  
+  virtual llvm::StringRef getName() const {
+    return "HTMLDiagnostics";
+  }
+
+  unsigned ProcessMacroPiece(llvm::raw_ostream& os,
+                             const PathDiagnosticMacroPiece& P,
+                             unsigned num);
+
+  void HandlePiece(Rewriter& R, FileID BugFileID,
+                   const PathDiagnosticPiece& P, unsigned num, unsigned max);
+
+  void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range,
+                      const char *HighlightStart = "<span class=\"mrange\">",
+                      const char *HighlightEnd = "</span>");
+
+  void ReportDiag(const PathDiagnostic& D,
+                  llvm::SmallVectorImpl<std::string> *FilesMade);
+};
+
+} // end anonymous namespace
+
+HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix,
+                                 const Preprocessor &pp)
+  : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
+    PP(pp) {
+  // All html files begin with "report"
+  FilePrefix.appendComponent("report");
+}
+
+PathDiagnosticClient*
+clang::CreateHTMLDiagnosticClient(const std::string& prefix,
+                                  const Preprocessor &PP) {
+  return new HTMLDiagnostics(prefix, PP);
+}
+
+//===----------------------------------------------------------------------===//
+// Report processing.
+//===----------------------------------------------------------------------===//
+
+void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+  if (!D)
+    return;
+
+  if (D->empty()) {
+    delete D;
+    return;
+  }
+
+  const_cast<PathDiagnostic*>(D)->flattenLocations();
+  BatchedDiags.push_back(D);
+}
+
+void
+HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
+{
+  while (!BatchedDiags.empty()) {
+    const PathDiagnostic* D = BatchedDiags.back();
+    BatchedDiags.pop_back();
+    ReportDiag(*D, FilesMade);
+    delete D;
+  }
+  
+  BatchedDiags.clear();
+}
+
+void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
+                                 llvm::SmallVectorImpl<std::string> *FilesMade){
+  // Create the HTML directory if it is missing.
+  if (!createdDir) {
+    createdDir = true;
+    std::string ErrorMsg;
+    Directory.createDirectoryOnDisk(true, &ErrorMsg);
+
+    if (!Directory.isDirectory()) {
+      llvm::errs() << "warning: could not create directory '"
+                   << Directory.str() << "'\n"
+                   << "reason: " << ErrorMsg << '\n';
+
+      noDir = true;
+
+      return;
+    }
+  }
+
+  if (noDir)
+    return;
+
+  const SourceManager &SMgr = D.begin()->getLocation().getManager();
+  FileID FID;
+
+  // Verify that the entire path is from the same FileID.
+  for (PathDiagnostic::const_iterator I = D.begin(), E = D.end(); I != E; ++I) {
+    FullSourceLoc L = I->getLocation().asLocation().getInstantiationLoc();
+
+    if (FID.isInvalid()) {
+      FID = SMgr.getFileID(L);
+    } else if (SMgr.getFileID(L) != FID)
+      return; // FIXME: Emit a warning?
+
+    // Check the source ranges.
+    for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
+                                             RE=I->ranges_end(); RI!=RE; ++RI) {
+
+      SourceLocation L = SMgr.getInstantiationLoc(RI->getBegin());
+
+      if (!L.isFileID() || SMgr.getFileID(L) != FID)
+        return; // FIXME: Emit a warning?
+
+      L = SMgr.getInstantiationLoc(RI->getEnd());
+
+      if (!L.isFileID() || SMgr.getFileID(L) != FID)
+        return; // FIXME: Emit a warning?
+    }
+  }
+
+  if (FID.isInvalid())
+    return; // FIXME: Emit a warning?
+
+  // Create a new rewriter to generate HTML.
+  Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());
+
+  // Process the path.
+  unsigned n = D.size();
+  unsigned max = n;
+
+  for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
+        I!=E; ++I, --n)
+    HandlePiece(R, FID, *I, n, max);
+
+  // Add line numbers, header, footer, etc.
+
+  // unsigned FID = R.getSourceMgr().getMainFileID();
+  html::EscapeText(R, FID);
+  html::AddLineNumbers(R, FID);
+
+  // If we have a preprocessor, relex the file and syntax highlight.
+  // We might not have a preprocessor if we come from a deserialized AST file,
+  // for example.
+
+  html::SyntaxHighlight(R, FID, PP);
+  html::HighlightMacros(R, FID, PP);
+
+  // Get the full directory name of the analyzed file.
+
+  const FileEntry* Entry = SMgr.getFileEntryForID(FID);
+
+  // This is a cludge; basically we want to append either the full
+  // working directory if we have no directory information.  This is
+  // a work in progress.
+
+  std::string DirName = "";
+
+  if (!llvm::sys::Path(Entry->getName()).isAbsolute()) {
+    llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
+    DirName = P.str() + "/";
+  }
+
+  // Add the name of the file as an <h1> tag.
+
+  {
+    std::string s;
+    llvm::raw_string_ostream os(s);
+
+    os << "<!-- REPORTHEADER -->\n"
+      << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
+          "<tr><td class=\"rowname\">File:</td><td>"
+      << html::EscapeText(DirName)
+      << html::EscapeText(Entry->getName())
+      << "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
+         "<a href=\"#EndPath\">line "
+      << (*D.rbegin()).getLocation().asLocation().getInstantiationLineNumber()
+      << ", column "
+      << (*D.rbegin()).getLocation().asLocation().getInstantiationColumnNumber()
+      << "</a></td></tr>\n"
+         "<tr><td class=\"rowname\">Description:</td><td>"
+      << D.getDescription() << "</td></tr>\n";
+
+    // Output any other meta data.
+
+    for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
+         I!=E; ++I) {
+      os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
+    }
+
+    os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
+          "<h3>Annotated Source Code</h3>\n";
+
+    R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
+  }
+
+  // Embed meta-data tags.
+  {
+    std::string s;
+    llvm::raw_string_ostream os(s);
+
+    const std::string& BugDesc = D.getDescription();
+    if (!BugDesc.empty())
+      os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
+
+    const std::string& BugType = D.getBugType();
+    if (!BugType.empty())
+      os << "\n<!-- BUGTYPE " << BugType << " -->\n";
+
+    const std::string& BugCategory = D.getCategory();
+    if (!BugCategory.empty())
+      os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
+
+    os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
+
+    os << "\n<!-- BUGLINE "
+       << D.back()->getLocation().asLocation().getInstantiationLineNumber()
+       << " -->\n";
+
+    os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n";
+
+    // Mark the end of the tags.
+    os << "\n<!-- BUGMETAEND -->\n";
+
+    // Insert the text.
+    R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
+  }
+
+  // Add CSS, header, and footer.
+
+  html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
+
+  // Get the rewrite buffer.
+  const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
+
+  if (!Buf) {
+    llvm::errs() << "warning: no diagnostics generated for main file.\n";
+    return;
+  }
+
+  // Create a path for the target HTML file.
+  llvm::sys::Path F(FilePrefix);
+  F.makeUnique(false, NULL);
+
+  // Rename the file with an HTML extension.
+  llvm::sys::Path H(F);
+  H.appendSuffix("html");
+  F.renamePathOnDisk(H, NULL);
+
+  std::string ErrorMsg;
+  llvm::raw_fd_ostream os(H.c_str(), ErrorMsg);
+
+  if (!ErrorMsg.empty()) {
+    (llvm::errs() << "warning: could not create file '" << F.str() 
+                  << "'\n").flush();
+    return;
+  }
+
+  if (FilesMade)
+    FilesMade->push_back(H.getLast());
+
+  // Emit the HTML to disk.
+  for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
+      os << *I;
+}
+
+void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
+                                  const PathDiagnosticPiece& P,
+                                  unsigned num, unsigned max) {
+
+  // For now, just draw a box above the line in question, and emit the
+  // warning.
+  FullSourceLoc Pos = P.getLocation().asLocation();
+
+  if (!Pos.isValid())
+    return;
+
+  SourceManager &SM = R.getSourceMgr();
+  assert(&Pos.getManager() == &SM && "SourceManagers are different!");
+  std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedInstantiationLoc(Pos);
+
+  if (LPosInfo.first != BugFileID)
+    return;
+
+  const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
+  const char* FileStart = Buf->getBufferStart();
+
+  // Compute the column number.  Rewind from the current position to the start
+  // of the line.
+  unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
+  const char *TokInstantiationPtr =Pos.getInstantiationLoc().getCharacterData();
+  const char *LineStart = TokInstantiationPtr-ColNo;
+
+  // Compute LineEnd.
+  const char *LineEnd = TokInstantiationPtr;
+  const char* FileEnd = Buf->getBufferEnd();
+  while (*LineEnd != '\n' && LineEnd != FileEnd)
+    ++LineEnd;
+
+  // Compute the margin offset by counting tabs and non-tabs.
+  unsigned PosNo = 0;
+  for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
+    PosNo += *c == '\t' ? 8 : 1;
+
+  // Create the html for the message.
+
+  const char *Kind = 0;
+  switch (P.getKind()) {
+  case PathDiagnosticPiece::Event:  Kind = "Event"; break;
+  case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
+    // Setting Kind to "Control" is intentional.
+  case PathDiagnosticPiece::Macro: Kind = "Control"; break;
+  }
+
+  std::string sbuf;
+  llvm::raw_string_ostream os(sbuf);
+
+  os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";
+
+  if (num == max)
+    os << "EndPath";
+  else
+    os << "Path" << num;
+
+  os << "\" class=\"msg";
+  if (Kind)
+    os << " msg" << Kind;
+  os << "\" style=\"margin-left:" << PosNo << "ex";
+
+  // Output a maximum size.
+  if (!isa<PathDiagnosticMacroPiece>(P)) {
+    // Get the string and determining its maximum substring.
+    const std::string& Msg = P.getString();
+    unsigned max_token = 0;
+    unsigned cnt = 0;
+    unsigned len = Msg.size();
+
+    for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
+      switch (*I) {
+      default:
+        ++cnt;
+        continue;
+      case ' ':
+      case '\t':
+      case '\n':
+        if (cnt > max_token) max_token = cnt;
+        cnt = 0;
+      }
+
+    if (cnt > max_token)
+      max_token = cnt;
+
+    // Determine the approximate size of the message bubble in em.
+    unsigned em;
+    const unsigned max_line = 120;
+
+    if (max_token >= max_line)
+      em = max_token / 2;
+    else {
+      unsigned characters = max_line;
+      unsigned lines = len / max_line;
+
+      if (lines > 0) {
+        for (; characters > max_token; --characters)
+          if (len / characters > lines) {
+            ++characters;
+            break;
+          }
+      }
+
+      em = characters / 2;
+    }
+
+    if (em < max_line/2)
+      os << "; max-width:" << em << "em";
+  }
+  else
+    os << "; max-width:100em";
+
+  os << "\">";
+
+  if (max > 1) {
+    os << "<table class=\"msgT\"><tr><td valign=\"top\">";
+    os << "<div class=\"PathIndex";
+    if (Kind) os << " PathIndex" << Kind;
+    os << "\">" << num << "</div>";
+    os << "</td><td>";
+  }
+
+  if (const PathDiagnosticMacroPiece *MP =
+        dyn_cast<PathDiagnosticMacroPiece>(&P)) {
+
+    os << "Within the expansion of the macro '";
+
+    // Get the name of the macro by relexing it.
+    {
+      FullSourceLoc L = MP->getLocation().asLocation().getInstantiationLoc();
+      assert(L.isFileID());
+      std::pair<const char*, const char*> BufferInfo = L.getBufferData();
+      const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first;
+      Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.first,
+                     MacroName, BufferInfo.second);
+
+      Token TheTok;
+      rawLexer.LexFromRawLexer(TheTok);
+      for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
+        os << MacroName[i];
+    }
+
+    os << "':\n";
+
+    if (max > 1)
+      os << "</td></tr></table>";
+
+    // Within a macro piece.  Write out each event.
+    ProcessMacroPiece(os, *MP, 0);
+  }
+  else {
+    os << html::EscapeText(P.getString());
+
+    if (max > 1)
+      os << "</td></tr></table>";
+  }
+
+  os << "</div></td></tr>";
+
+  // Insert the new html.
+  unsigned DisplayPos = LineEnd - FileStart;
+  SourceLocation Loc =
+    SM.getLocForStartOfFile(LPosInfo.first).getFileLocWithOffset(DisplayPos);
+
+  R.InsertTextBefore(Loc, os.str());
+
+  // Now highlight the ranges.
+  for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
+        I != E; ++I)
+    HighlightRange(R, LPosInfo.first, *I);
+
+#if 0
+  // If there is a code insertion hint, insert that code.
+  // FIXME: This code is disabled because it seems to mangle the HTML
+  // output. I'm leaving it here because it's generally the right idea,
+  // but needs some help from someone more familiar with the rewriter.
+  for (const CodeModificationHint *Hint = P.code_modifications_begin(),
+                               *HintEnd = P.code_modifications_end();
+       Hint != HintEnd; ++Hint) {
+    if (Hint->RemoveRange.isValid()) {
+      HighlightRange(R, LPosInfo.first, Hint->RemoveRange,
+                     "<span class=\"CodeRemovalHint\">", "</span>");
+    }
+    if (Hint->InsertionLoc.isValid()) {
+      std::string EscapedCode = html::EscapeText(Hint->CodeToInsert, true);
+      EscapedCode = "<span class=\"CodeInsertionHint\">" + EscapedCode
+        + "</span>";
+      R.InsertTextBefore(Hint->InsertionLoc, EscapedCode);
+    }
+  }
+#endif
+}
+
+static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) {
+  llvm::SmallVector<char, 10> buf;
+
+  do {
+    unsigned x = n % ('z' - 'a');
+    buf.push_back('a' + x);
+    n = n / ('z' - 'a');
+  } while (n);
+
+  assert(!buf.empty());
+
+  for (llvm::SmallVectorImpl<char>::reverse_iterator I=buf.rbegin(),
+       E=buf.rend(); I!=E; ++I)
+    os << *I;
+}
+
+unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os,
+                                            const PathDiagnosticMacroPiece& P,
+                                            unsigned num) {
+
+  for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
+        I!=E; ++I) {
+
+    if (const PathDiagnosticMacroPiece *MP =
+          dyn_cast<PathDiagnosticMacroPiece>(*I)) {
+      num = ProcessMacroPiece(os, *MP, num);
+      continue;
+    }
+
+    if (PathDiagnosticEventPiece *EP = dyn_cast<PathDiagnosticEventPiece>(*I)) {
+      os << "<div class=\"msg msgEvent\" style=\"width:94%; "
+            "margin-left:5px\">"
+            "<table class=\"msgT\"><tr>"
+            "<td valign=\"top\"><div class=\"PathIndex PathIndexEvent\">";
+      EmitAlphaCounter(os, num++);
+      os << "</div></td><td valign=\"top\">"
+         << html::EscapeText(EP->getString())
+         << "</td></tr></table></div>\n";
+    }
+  }
+
+  return num;
+}
+
+void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
+                                     SourceRange Range,
+                                     const char *HighlightStart,
+                                     const char *HighlightEnd) {
+  SourceManager &SM = R.getSourceMgr();
+  const LangOptions &LangOpts = R.getLangOpts();
+
+  SourceLocation InstantiationStart = SM.getInstantiationLoc(Range.getBegin());
+  unsigned StartLineNo = SM.getInstantiationLineNumber(InstantiationStart);
+
+  SourceLocation InstantiationEnd = SM.getInstantiationLoc(Range.getEnd());
+  unsigned EndLineNo = SM.getInstantiationLineNumber(InstantiationEnd);
+
+  if (EndLineNo < StartLineNo)
+    return;
+
+  if (SM.getFileID(InstantiationStart) != BugFileID ||
+      SM.getFileID(InstantiationEnd) != BugFileID)
+    return;
+
+  // Compute the column number of the end.
+  unsigned EndColNo = SM.getInstantiationColumnNumber(InstantiationEnd);
+  unsigned OldEndColNo = EndColNo;
+
+  if (EndColNo) {
+    // Add in the length of the token, so that we cover multi-char tokens.
+    EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1;
+  }
+
+  // Highlight the range.  Make the span tag the outermost tag for the
+  // selected range.
+
+  SourceLocation E =
+    InstantiationEnd.getFileLocWithOffset(EndColNo - OldEndColNo);
+
+  html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
+}
diff --git a/lib/Frontend/HTMLPrint.cpp b/lib/Frontend/HTMLPrint.cpp
new file mode 100644
index 0000000..9ea8cb3
--- /dev/null
+++ b/lib/Frontend/HTMLPrint.cpp
@@ -0,0 +1,94 @@
+//===--- HTMLPrint.cpp - Source code -> HTML pretty-printing --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Pretty-printing of source code to HTML.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Functional HTML pretty-printing.
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class HTMLPrinter : public ASTConsumer {
+    Rewriter R;
+    llvm::raw_ostream *Out;
+    Preprocessor &PP;
+    bool SyntaxHighlight, HighlightMacros;
+
+  public:
+    HTMLPrinter(llvm::raw_ostream *OS, Preprocessor &pp,
+                bool _SyntaxHighlight, bool _HighlightMacros)
+      : Out(OS), PP(pp), SyntaxHighlight(_SyntaxHighlight),
+        HighlightMacros(_HighlightMacros) {}
+
+    void Initialize(ASTContext &context);
+    void HandleTranslationUnit(ASTContext &Ctx);
+  };
+}
+
+ASTConsumer* clang::CreateHTMLPrinter(llvm::raw_ostream *OS,
+                                      Preprocessor &PP,
+                                      bool SyntaxHighlight,
+                                      bool HighlightMacros) {
+  return new HTMLPrinter(OS, PP, SyntaxHighlight, HighlightMacros);
+}
+
+void HTMLPrinter::Initialize(ASTContext &context) {
+  R.setSourceMgr(context.getSourceManager(), context.getLangOptions());
+}
+
+void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
+  if (PP.getDiagnostics().hasErrorOccurred())
+    return;
+
+  // Format the file.
+  FileID FID = R.getSourceMgr().getMainFileID();
+  const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FID);
+  const char* Name;
+  // In some cases, in particular the case where the input is from stdin,
+  // there is no entry.  Fall back to the memory buffer for a name in those
+  // cases.
+  if (Entry)
+    Name = Entry->getName();
+  else
+    Name = R.getSourceMgr().getBuffer(FID)->getBufferIdentifier();
+
+  html::AddLineNumbers(R, FID);
+  html::AddHeaderFooterInternalBuiltinCSS(R, FID, Name);
+
+  // If we have a preprocessor, relex the file and syntax highlight.
+  // We might not have a preprocessor if we come from a deserialized AST file,
+  // for example.
+
+  if (SyntaxHighlight) html::SyntaxHighlight(R, FID, PP);
+  if (HighlightMacros) html::HighlightMacros(R, FID, PP);
+  html::EscapeText(R, FID, false, true);
+
+  // Emit the HTML.
+  const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
+  char *Buffer = (char*)malloc(RewriteBuf.size());
+  std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
+  Out->write(Buffer, RewriteBuf.size());
+  free(Buffer);
+}
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
new file mode 100644
index 0000000..85287dd
--- /dev/null
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -0,0 +1,754 @@
+//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the InitHeaderSearch class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+#include "llvm/Config/config.h"
+#ifdef _MSC_VER
+  #define WIN32_LEAN_AND_MEAN 1
+  #include <windows.h>
+#endif
+using namespace clang;
+using namespace clang::frontend;
+
+namespace {
+
+/// InitHeaderSearch - This class makes it easier to set the search paths of
+///  a HeaderSearch object. InitHeaderSearch stores several search path lists
+///  internally, which can be sent to a HeaderSearch object in one swoop.
+class InitHeaderSearch {
+  std::vector<DirectoryLookup> IncludeGroup[4];
+  HeaderSearch& Headers;
+  bool Verbose;
+  std::string isysroot;
+
+public:
+
+  InitHeaderSearch(HeaderSearch &HS,
+      bool verbose = false, const std::string &iSysroot = "")
+    : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
+
+  /// AddPath - Add the specified path to the specified group list.
+  void AddPath(const llvm::Twine &Path, IncludeDirGroup Group,
+               bool isCXXAware, bool isUserSupplied,
+               bool isFramework, bool IgnoreSysRoot = false);
+
+  /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu
+  ///  libstdc++.
+  void AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
+                                   llvm::StringRef ArchDir,
+                                   llvm::StringRef Dir32,
+                                   llvm::StringRef Dir64,
+                                   const llvm::Triple &triple);
+
+  /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW
+  ///  libstdc++.
+  void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
+                                     llvm::StringRef Arch,
+                                     llvm::StringRef Version);
+
+  /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
+  /// separator. The processing follows that of the CPATH variable for gcc.
+  void AddDelimitedPaths(llvm::StringRef String);
+
+  // AddDefaultCIncludePaths - Add paths that should always be searched.
+  void AddDefaultCIncludePaths(const llvm::Triple &triple);
+
+  // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
+  //  compiling c++.
+  void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
+
+  /// AddDefaultSystemIncludePaths - Adds the default system include paths so
+  ///  that e.g. stdio.h is found.
+  void AddDefaultSystemIncludePaths(const LangOptions &Lang,
+                                    const llvm::Triple &triple);
+
+  /// Realize - Merges all search path lists into one list and send it to
+  /// HeaderSearch.
+  void Realize();
+};
+
+}
+
+void InitHeaderSearch::AddPath(const llvm::Twine &Path,
+                               IncludeDirGroup Group, bool isCXXAware,
+                               bool isUserSupplied, bool isFramework,
+                               bool IgnoreSysRoot) {
+  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
+  FileManager &FM = Headers.getFileMgr();
+
+  // Compute the actual path, taking into consideration -isysroot.
+  llvm::SmallString<256> MappedPathStr;
+  llvm::raw_svector_ostream MappedPath(MappedPathStr);
+
+  // Handle isysroot.
+  if (Group == System && !IgnoreSysRoot) {
+    // FIXME: Portability.  This should be a sys::Path interface, this doesn't
+    // handle things like C:\ right, nor win32 \\network\device\blah.
+    if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present.
+      MappedPath << isysroot;
+  }
+
+  Path.print(MappedPath);
+
+  // Compute the DirectoryLookup type.
+  SrcMgr::CharacteristicKind Type;
+  if (Group == Quoted || Group == Angled)
+    Type = SrcMgr::C_User;
+  else if (isCXXAware)
+    Type = SrcMgr::C_System;
+  else
+    Type = SrcMgr::C_ExternCSystem;
+
+
+  // If the directory exists, add it.
+  if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) {
+    IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
+                                                  isFramework));
+    return;
+  }
+
+  // Check to see if this is an apple-style headermap (which are not allowed to
+  // be frameworks).
+  if (!isFramework) {
+    if (const FileEntry *FE = FM.getFile(MappedPath.str())) {
+      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
+        // It is a headermap, add it to the search path.
+        IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
+        return;
+      }
+    }
+  }
+
+  if (Verbose)
+    llvm::errs() << "ignoring nonexistent directory \""
+                 << MappedPath.str() << "\"\n";
+}
+
+
+void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) {
+  if (at.empty()) // Empty string should not add '.' path.
+    return;
+
+  llvm::StringRef::size_type delim;
+  while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) {
+    if (delim == 0)
+      AddPath(".", Angled, false, true, false);
+    else
+      AddPath(at.substr(0, delim), Angled, false, true, false);
+    at = at.substr(delim + 1);
+  }
+
+  if (at.empty())
+    AddPath(".", Angled, false, true, false);
+  else
+    AddPath(at, Angled, false, true, false);
+}
+
+void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
+                                                   llvm::StringRef ArchDir,
+                                                   llvm::StringRef Dir32,
+                                                   llvm::StringRef Dir64,
+                                                   const llvm::Triple &triple) {
+  // Add the base dir
+  AddPath(Base, System, true, false, false);
+
+  // Add the multilib dirs
+  llvm::Triple::ArchType arch = triple.getArch();
+  bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
+  if (is64bit)
+    AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
+  else
+    AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
+
+  // Add the backward dir
+  AddPath(Base + "/backward", System, true, false, false);
+}
+
+void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
+                                                     llvm::StringRef Arch,
+                                                     llvm::StringRef Version) {
+  AddPath(Base + "/" + Arch + "/" + Version + "/include",
+          System, true, false, false);
+  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
+          System, true, false, false);
+  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
+          System, true, false, false);
+}
+
+  // FIXME: This probably should goto to some platform utils place.
+#ifdef _MSC_VER
+
+  // Read registry string.
+  // This also supports a means to look for high-versioned keys by use
+  // of a $VERSION placeholder in the key path.
+  // $VERSION in the key path is a placeholder for the version number,
+  // causing the highest value path to be searched for and used.
+  // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
+  // There can be additional characters in the component.  Only the numberic
+  // characters are compared.
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+                                    char *value, size_t maxLength) {
+  HKEY hRootKey = NULL;
+  HKEY hKey = NULL;
+  const char* subKey = NULL;
+  DWORD valueType;
+  DWORD valueSize = maxLength - 1;
+  long lResult;
+  bool returnValue = false;
+  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
+    hRootKey = HKEY_CLASSES_ROOT;
+    subKey = keyPath + 18;
+  }
+  else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
+    hRootKey = HKEY_USERS;
+    subKey = keyPath + 11;
+  }
+  else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
+    hRootKey = HKEY_LOCAL_MACHINE;
+    subKey = keyPath + 19;
+  }
+  else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
+    hRootKey = HKEY_CURRENT_USER;
+    subKey = keyPath + 18;
+  }
+  else
+    return(false);
+  const char *placeHolder = strstr(subKey, "$VERSION");
+  char bestName[256];
+  bestName[0] = '\0';
+  // If we have a $VERSION placeholder, do the highest-version search.
+  if (placeHolder) {
+    const char *keyEnd = placeHolder - 1;
+    const char *nextKey = placeHolder;
+    // Find end of previous key.
+    while ((keyEnd > subKey) && (*keyEnd != '\\'))
+      keyEnd--;
+    // Find end of key containing $VERSION.
+    while (*nextKey && (*nextKey != '\\'))
+      nextKey++;
+    size_t partialKeyLength = keyEnd - subKey;
+    char partialKey[256];
+    if (partialKeyLength > sizeof(partialKey))
+      partialKeyLength = sizeof(partialKey);
+    strncpy(partialKey, subKey, partialKeyLength);
+    partialKey[partialKeyLength] = '\0';
+    HKEY hTopKey = NULL;
+    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
+    if (lResult == ERROR_SUCCESS) {
+      char keyName[256];
+      int bestIndex = -1;
+      double bestValue = 0.0;
+      DWORD index, size = sizeof(keyName) - 1;
+      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
+          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
+        const char *sp = keyName;
+        while (*sp && !isdigit(*sp))
+          sp++;
+        if (!*sp)
+          continue;
+        const char *ep = sp + 1;
+        while (*ep && (isdigit(*ep) || (*ep == '.')))
+          ep++;
+        char numBuf[32];
+        strncpy(numBuf, sp, sizeof(numBuf) - 1);
+        numBuf[sizeof(numBuf) - 1] = '\0';
+        double value = strtod(numBuf, NULL);
+        if (value > bestValue) {
+          bestIndex = (int)index;
+          bestValue = value;
+          strcpy(bestName, keyName);
+        }
+        size = sizeof(keyName) - 1;
+      }
+      // If we found the highest versioned key, open the key and get the value.
+      if (bestIndex != -1) {
+        // Append rest of key.
+        strncat(bestName, nextKey, sizeof(bestName) - 1);
+        bestName[sizeof(bestName) - 1] = '\0';
+        // Open the chosen key path remainder.
+        lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
+        if (lResult == ERROR_SUCCESS) {
+          lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
+            (LPBYTE)value, &valueSize);
+          if (lResult == ERROR_SUCCESS)
+            returnValue = true;
+          RegCloseKey(hKey);
+        }
+      }
+      RegCloseKey(hTopKey);
+    }
+  }
+  else {
+    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
+    if (lResult == ERROR_SUCCESS) {
+      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
+        (LPBYTE)value, &valueSize);
+      if (lResult == ERROR_SUCCESS)
+        returnValue = true;
+      RegCloseKey(hKey);
+    }
+  }
+  return(returnValue);
+}
+#else // _MSC_VER
+  // Read registry string.
+static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
+  return(false);
+}
+#endif // _MSC_VER
+
+  // Get Visual Studio installation directory.
+static bool getVisualStudioDir(std::string &path) {
+  char vsIDEInstallDir[256];
+  // Try the Windows registry first.
+  bool hasVCDir = getSystemRegistryString(
+    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
+    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
+    // If we have both vc80 and vc90, pick version we were compiled with. 
+  if (hasVCDir && vsIDEInstallDir[0]) {
+    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
+    if (p)
+      *p = '\0';
+    path = vsIDEInstallDir;
+    return(true);
+  }
+  else {
+    // Try the environment.
+    const char* vs90comntools = getenv("VS90COMNTOOLS");
+    const char* vs80comntools = getenv("VS80COMNTOOLS");
+    const char* vscomntools = NULL;
+      // If we have both vc80 and vc90, pick version we were compiled with. 
+    if (vs90comntools && vs80comntools) {
+      #if (_MSC_VER >= 1500)  // VC90
+          vscomntools = vs90comntools;
+      #elif (_MSC_VER == 1400) // VC80
+          vscomntools = vs80comntools;
+      #else
+          vscomntools = vs90comntools;
+      #endif
+    }
+    else if (vs90comntools)
+      vscomntools = vs90comntools;
+    else if (vs80comntools)
+      vscomntools = vs80comntools;
+    if (vscomntools && *vscomntools) {
+      char *p = (char*)strstr(vscomntools, "\\Common7\\Tools");
+      if (p)
+        *p = '\0';
+      path = vscomntools;
+      return(true);
+    }
+    else
+      return(false);
+  }
+  return(false);
+}
+
+  // Get Windows SDK installation directory.
+static bool getWindowsSDKDir(std::string &path) {
+  char windowsSDKInstallDir[256];
+  // Try the Windows registry.
+  bool hasSDKDir = getSystemRegistryString(
+   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
+    "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1);
+    // If we have both vc80 and vc90, pick version we were compiled with. 
+  if (hasSDKDir && windowsSDKInstallDir[0]) {
+    path = windowsSDKInstallDir;
+    return(true);
+  }
+  return(false);
+}
+
+void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
+  // FIXME: temporary hack: hard-coded paths.
+  llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
+  if (CIncludeDirs != "") {
+    llvm::SmallVector<llvm::StringRef, 5> dirs;
+    CIncludeDirs.split(dirs, ":");
+    for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
+         i != dirs.end();
+         ++i) 
+      AddPath(*i, System, false, false, false);
+    return;
+  }
+  llvm::Triple::OSType os = triple.getOS();
+  switch (os) {
+  case llvm::Triple::Win32:
+    {
+      std::string VSDir;
+      std::string WindowsSDKDir;
+      if (getVisualStudioDir(VSDir)) {
+        AddPath(VSDir + "\\VC\\include", System, false, false, false);
+        if (getWindowsSDKDir(WindowsSDKDir))
+          AddPath(WindowsSDKDir, System, false, false, false);
+        else
+          AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
+            System, false, false, false);
+      }
+      else {
+          // Default install paths.
+        AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
+          System, false, false, false);
+        AddPath(
+        "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
+          System, false, false, false);
+        AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include",
+          System, false, false, false);
+        AddPath(
+        "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include",
+          System, false, false, false);
+          // For some clang developers.
+        AddPath("G:/Program Files/Microsoft Visual Studio 9.0/VC/include",
+          System, false, false, false);
+        AddPath(
+        "G:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
+          System, false, false, false);
+      }
+    }
+    break;
+  case llvm::Triple::MinGW64:
+  case llvm::Triple::MinGW32:
+    AddPath("c:/mingw/include", System, true, false, false);
+    break;
+  default:
+    break;
+  }
+
+  AddPath("/usr/local/include", System, false, false, false);
+  AddPath("/usr/include", System, false, false, false);
+}
+
+void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
+  llvm::Triple::OSType os = triple.getOS();
+  llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
+  if (CxxIncludeRoot != "") {
+    llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
+    if (CxxIncludeArch == "")
+      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
+                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
+    else
+      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
+                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
+    return;
+  }
+  // FIXME: temporary hack: hard-coded paths.
+  switch (os) {
+  case llvm::Triple::Cygwin:
+    AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
+        System, true, false, false);
+    AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
+        System, true, false, false);
+    break;
+  case llvm::Triple::MinGW64:
+    // Try gcc 4.4.0
+    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
+    // Try gcc 4.3.0
+    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
+    // Fall through.
+  case llvm::Triple::MinGW32:
+    // Try gcc 4.4.0
+    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
+    // Try gcc 4.3.0
+    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
+    break;
+  case llvm::Triple::Darwin:
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+                                "i686-apple-darwin10", "", "x86_64", triple);
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
+                                "i686-apple-darwin8", "", "", triple);
+    break;
+  case llvm::Triple::DragonFly:
+    AddPath("/usr/include/c++/4.1", System, true, false, false);
+    break;
+  case llvm::Triple::Linux:
+    // Exherbo (2010-01-25)
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
+                                "x86_64-pc-linux-gnu", "32", "", triple);
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
+                                "i686-pc-linux-gnu", "", "", triple);
+    // Debian sid
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+                                "x86_64-linux-gnu", "32", "", triple);
+    // Ubuntu 7.10 - Gutsy Gibbon
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
+                                "i486-linux-gnu", "", "", triple);
+    // Ubuntu 9.04
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
+                                "x86_64-linux-gnu","32", "", triple);
+    // Ubuntu 9.10
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+                                "x86_64-linux-gnu", "32", "", triple);
+    // Fedora 8
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
+                                "i386-redhat-linux", "", "", triple);
+    // Fedora 9
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
+                                "i386-redhat-linux", "", "", triple);
+    // Fedora 10
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+                                "i386-redhat-linux","", "", triple);
+
+    // Fedora 10 x86_64
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+                                "x86_64-redhat-linux", "32", "", triple);
+
+    // Fedora 11
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+                                "i586-redhat-linux","", "", triple);
+
+    // Fedora 12
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+                                "i686-redhat-linux","", "", triple);
+
+    // openSUSE 11.1 32 bit
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+                                "i586-suse-linux", "", "", triple);
+    // openSUSE 11.1 64 bit
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+                                "x86_64-suse-linux", "32", "", triple);
+    // openSUSE 11.2
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+                                "i586-suse-linux", "", "", triple);
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+                                "x86_64-suse-linux", "", "", triple);
+    // Arch Linux 2008-06-24
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+                                "i686-pc-linux-gnu", "", "", triple);
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+                                "x86_64-unknown-linux-gnu", "", "", triple);
+    // Gentoo x86 2009.1 stable
+    AddGnuCPlusPlusIncludePaths(
+      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+      "i686-pc-linux-gnu", "", "", triple);
+    // Gentoo x86 2009.0 stable
+    AddGnuCPlusPlusIncludePaths(
+      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
+      "i686-pc-linux-gnu", "", "", triple);
+    // Gentoo x86 2008.0 stable
+    AddGnuCPlusPlusIncludePaths(
+      "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
+      "i686-pc-linux-gnu", "", "", triple);
+    // Ubuntu 8.10
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+                                "i486-pc-linux-gnu", "", "", triple);
+    // Ubuntu 9.04
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+                                "i486-linux-gnu","", "", triple);
+    // Gentoo amd64 stable
+    AddGnuCPlusPlusIncludePaths(
+        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
+        "i686-pc-linux-gnu", "", "", triple);
+    break;
+  case llvm::Triple::FreeBSD:
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
+    break;
+  case llvm::Triple::Solaris:
+    // Solaris - Fall though..
+  case llvm::Triple::AuroraUX:
+    // AuroraUX
+    AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
+                                "i386-pc-solaris2.11", "", "", triple);
+    break;
+  default:
+    break;
+  }
+}
+
+void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
+                                                    const llvm::Triple &triple) {
+  if (Lang.CPlusPlus)
+    AddDefaultCPlusPlusIncludePaths(triple);
+
+  AddDefaultCIncludePaths(triple);
+
+  // Add the default framework include paths on Darwin.
+  if (triple.getOS() == llvm::Triple::Darwin) {
+    AddPath("/System/Library/Frameworks", System, true, false, true);
+    AddPath("/Library/Frameworks", System, true, false, true);
+  }
+}
+
+/// RemoveDuplicates - If there are duplicate directory entries in the specified
+/// search list, remove the later (dead) ones.
+static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
+                             bool Verbose) {
+  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
+  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
+  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
+  for (unsigned i = 0; i != SearchList.size(); ++i) {
+    unsigned DirToRemove = i;
+
+    const DirectoryLookup &CurEntry = SearchList[i];
+
+    if (CurEntry.isNormalDir()) {
+      // If this isn't the first time we've seen this dir, remove it.
+      if (SeenDirs.insert(CurEntry.getDir()))
+        continue;
+    } else if (CurEntry.isFramework()) {
+      // If this isn't the first time we've seen this framework dir, remove it.
+      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
+        continue;
+    } else {
+      assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
+      // If this isn't the first time we've seen this headermap, remove it.
+      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
+        continue;
+    }
+
+    // If we have a normal #include dir/framework/headermap that is shadowed
+    // later in the chain by a system include location, we actually want to
+    // ignore the user's request and drop the user dir... keeping the system
+    // dir.  This is weird, but required to emulate GCC's search path correctly.
+    //
+    // Since dupes of system dirs are rare, just rescan to find the original
+    // that we're nuking instead of using a DenseMap.
+    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
+      // Find the dir that this is the same of.
+      unsigned FirstDir;
+      for (FirstDir = 0; ; ++FirstDir) {
+        assert(FirstDir != i && "Didn't find dupe?");
+
+        const DirectoryLookup &SearchEntry = SearchList[FirstDir];
+
+        // If these are different lookup types, then they can't be the dupe.
+        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
+          continue;
+
+        bool isSame;
+        if (CurEntry.isNormalDir())
+          isSame = SearchEntry.getDir() == CurEntry.getDir();
+        else if (CurEntry.isFramework())
+          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
+        else {
+          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
+          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
+        }
+
+        if (isSame)
+          break;
+      }
+
+      // If the first dir in the search path is a non-system dir, zap it
+      // instead of the system one.
+      if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
+        DirToRemove = FirstDir;
+    }
+
+    if (Verbose) {
+      llvm::errs() << "ignoring duplicate directory \""
+                   << CurEntry.getName() << "\"\n";
+      if (DirToRemove != i)
+        llvm::errs() << "  as it is a non-system directory that duplicates "
+                     << "a system directory\n";
+    }
+
+    // This is reached if the current entry is a duplicate.  Remove the
+    // DirToRemove (usually the current dir).
+    SearchList.erase(SearchList.begin()+DirToRemove);
+    --i;
+  }
+}
+
+
+void InitHeaderSearch::Realize() {
+  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
+  std::vector<DirectoryLookup> SearchList;
+  SearchList = IncludeGroup[Angled];
+  SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
+                    IncludeGroup[System].end());
+  SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
+                    IncludeGroup[After].end());
+  RemoveDuplicates(SearchList, Verbose);
+  RemoveDuplicates(IncludeGroup[Quoted], Verbose);
+
+  // Prepend QUOTED list on the search list.
+  SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
+                    IncludeGroup[Quoted].end());
+
+
+  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
+  Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
+                         DontSearchCurDir);
+
+  // If verbose, print the list of directories that will be searched.
+  if (Verbose) {
+    llvm::errs() << "#include \"...\" search starts here:\n";
+    unsigned QuotedIdx = IncludeGroup[Quoted].size();
+    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
+      if (i == QuotedIdx)
+        llvm::errs() << "#include <...> search starts here:\n";
+      const char *Name = SearchList[i].getName();
+      const char *Suffix;
+      if (SearchList[i].isNormalDir())
+        Suffix = "";
+      else if (SearchList[i].isFramework())
+        Suffix = " (framework directory)";
+      else {
+        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
+        Suffix = " (headermap)";
+      }
+      llvm::errs() << " " << Name << Suffix << "\n";
+    }
+    llvm::errs() << "End of search list.\n";
+  }
+}
+
+void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
+                                     const HeaderSearchOptions &HSOpts,
+                                     const LangOptions &Lang,
+                                     const llvm::Triple &Triple) {
+  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
+
+  // Add the user defined entries.
+  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
+    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
+    Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
+                 false);
+  }
+
+  // Add entries from CPATH and friends.
+  Init.AddDelimitedPaths(HSOpts.EnvIncPath);
+  if (Lang.CPlusPlus && Lang.ObjC1)
+    Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
+  else if (Lang.CPlusPlus)
+    Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
+  else if (Lang.ObjC1)
+    Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
+  else
+    Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
+
+  if (HSOpts.UseBuiltinIncludes) {
+    // Ignore the sys root, we *always* look for clang headers relative to
+    // supplied path.
+    llvm::sys::Path P(HSOpts.ResourceDir);
+    P.appendComponent("include");
+    Init.AddPath(P.str(), System, false, false, false, /*IgnoreSysRoot=*/ true);
+  }
+
+  if (HSOpts.UseStandardIncludes)
+    Init.AddDefaultSystemIncludePaths(Lang, Triple);
+
+  Init.Realize();
+}
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
new file mode 100644
index 0000000..9aaf132
--- /dev/null
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -0,0 +1,547 @@
+//===--- InitPreprocessor.cpp - PP initialization code. ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the clang::InitializePreprocessor function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/PreprocessorOptions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Path.h"
+using namespace clang;
+
+// Append a #define line to Buf for Macro.  Macro should be of the form XXX,
+// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
+// "#define XXX Y z W".  To get a #define with no value, use "XXX=".
+static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro,
+                               Diagnostic &Diags) {
+  std::pair<llvm::StringRef, llvm::StringRef> MacroPair = Macro.split('=');
+  llvm::StringRef MacroName = MacroPair.first;
+  llvm::StringRef MacroBody = MacroPair.second;
+  if (MacroName.size() != Macro.size()) {
+    // Per GCC -D semantics, the macro ends at \n if it exists.
+    llvm::StringRef::size_type End = MacroBody.find_first_of("\n\r");
+    if (End != llvm::StringRef::npos)
+      Diags.Report(diag::warn_fe_macro_contains_embedded_newline)
+        << MacroName;
+    Builder.defineMacro(MacroName, MacroBody.substr(0, End));
+  } else {
+    // Push "macroname 1".
+    Builder.defineMacro(Macro);
+  }
+}
+
+std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
+  // Implicit include paths should be resolved relative to the current
+  // working directory first, and then use the regular header search
+  // mechanism. The proper way to handle this is to have the
+  // predefines buffer located at the current working directory, but
+  // it has not file entry. For now, workaround this by using an
+  // absolute path if we find the file here, and otherwise letting
+  // header search handle it.
+  llvm::sys::Path Path(File);
+  Path.makeAbsolute();
+  if (!Path.exists())
+    Path = File;
+
+  return Lexer::Stringify(Path.str());
+}
+
+/// AddImplicitInclude - Add an implicit #include of the specified file to the
+/// predefines buffer.
+static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File) {
+  Builder.append("#include \"" +
+                 llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+}
+
+static void AddImplicitIncludeMacros(MacroBuilder &Builder,
+                                     llvm::StringRef File) {
+  Builder.append("#__include_macros \"" +
+                 llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+  // Marker token to stop the __include_macros fetch loop.
+  Builder.append("##"); // ##?
+}
+
+/// AddImplicitIncludePTH - Add an implicit #include using the original file
+///  used to generate a PTH cache.
+static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
+                                  llvm::StringRef ImplicitIncludePTH) {
+  PTHManager *P = PP.getPTHManager();
+  assert(P && "No PTHManager.");
+  const char *OriginalFile = P->getOriginalSourceFile();
+
+  if (!OriginalFile) {
+    PP.getDiagnostics().Report(diag::err_fe_pth_file_has_no_source_header)
+      << ImplicitIncludePTH;
+    return;
+  }
+
+  AddImplicitInclude(Builder, OriginalFile);
+}
+
+/// PickFP - This is used to pick a value based on the FP semantics of the
+/// specified FP model.
+template <typename T>
+static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal,
+                T IEEEDoubleVal, T X87DoubleExtendedVal, T PPCDoubleDoubleVal,
+                T IEEEQuadVal) {
+  if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle)
+    return IEEESingleVal;
+  if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEdouble)
+    return IEEEDoubleVal;
+  if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::x87DoubleExtended)
+    return X87DoubleExtendedVal;
+  if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::PPCDoubleDouble)
+    return PPCDoubleDoubleVal;
+  assert(Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEquad);
+  return IEEEQuadVal;
+}
+
+static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix,
+                              const llvm::fltSemantics *Sem) {
+  const char *DenormMin, *Epsilon, *Max, *Min;
+  DenormMin = PickFP(Sem, "1.40129846e-45F", "4.9406564584124654e-324",
+                     "3.64519953188247460253e-4951L",
+                     "4.94065645841246544176568792868221e-324L",
+                     "6.47517511943802511092443895822764655e-4966L");
+  int Digits = PickFP(Sem, 6, 15, 18, 31, 33);
+  Epsilon = PickFP(Sem, "1.19209290e-7F", "2.2204460492503131e-16",
+                   "1.08420217248550443401e-19L",
+                   "4.94065645841246544176568792868221e-324L",
+                   "1.92592994438723585305597794258492732e-34L");
+  int MantissaDigits = PickFP(Sem, 24, 53, 64, 106, 113);
+  int Min10Exp = PickFP(Sem, -37, -307, -4931, -291, -4931);
+  int Max10Exp = PickFP(Sem, 38, 308, 4932, 308, 4932);
+  int MinExp = PickFP(Sem, -125, -1021, -16381, -968, -16381);
+  int MaxExp = PickFP(Sem, 128, 1024, 16384, 1024, 16384);
+  Min = PickFP(Sem, "1.17549435e-38F", "2.2250738585072014e-308",
+               "3.36210314311209350626e-4932L",
+               "2.00416836000897277799610805135016e-292L",
+               "3.36210314311209350626267781732175260e-4932L");
+  Max = PickFP(Sem, "3.40282347e+38F", "1.7976931348623157e+308",
+               "1.18973149535723176502e+4932L",
+               "1.79769313486231580793728971405301e+308L",
+               "1.18973149535723176508575932662800702e+4932L");
+
+  llvm::SmallString<32> DefPrefix;
+  DefPrefix = "__";
+  DefPrefix += Prefix;
+  DefPrefix += "_";
+
+  Builder.defineMacro(DefPrefix + "DENORM_MIN__", DenormMin);
+  Builder.defineMacro(DefPrefix + "HAS_DENORM__");
+  Builder.defineMacro(DefPrefix + "DIG__", llvm::Twine(Digits));
+  Builder.defineMacro(DefPrefix + "EPSILON__", llvm::Twine(Epsilon));
+  Builder.defineMacro(DefPrefix + "HAS_INFINITY__");
+  Builder.defineMacro(DefPrefix + "HAS_QUIET_NAN__");
+  Builder.defineMacro(DefPrefix + "MANT_DIG__", llvm::Twine(MantissaDigits));
+
+  Builder.defineMacro(DefPrefix + "MAX_10_EXP__", llvm::Twine(Max10Exp));
+  Builder.defineMacro(DefPrefix + "MAX_EXP__", llvm::Twine(MaxExp));
+  Builder.defineMacro(DefPrefix + "MAX__", llvm::Twine(Max));
+
+  Builder.defineMacro(DefPrefix + "MIN_10_EXP__","("+llvm::Twine(Min10Exp)+")");
+  Builder.defineMacro(DefPrefix + "MIN_EXP__", "("+llvm::Twine(MinExp)+")");
+  Builder.defineMacro(DefPrefix + "MIN__", llvm::Twine(Min));
+}
+
+
+/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro
+/// named MacroName with the max value for a type with width 'TypeWidth' a
+/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
+static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth,
+                           llvm::StringRef ValSuffix, bool isSigned,
+                           MacroBuilder& Builder) {
+  long long MaxVal;
+  if (isSigned)
+    MaxVal = (1LL << (TypeWidth - 1)) - 1;
+  else
+    MaxVal = ~0LL >> (64-TypeWidth);
+
+  Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix);
+}
+
+/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
+/// the width, suffix, and signedness of the given type
+static void DefineTypeSize(llvm::StringRef MacroName, TargetInfo::IntType Ty,
+                           const TargetInfo &TI, MacroBuilder &Builder) {
+  DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), 
+                 TI.isTypeSigned(Ty), Builder);
+}
+
+static void DefineType(const llvm::Twine &MacroName, TargetInfo::IntType Ty,
+                       MacroBuilder &Builder) {
+  Builder.defineMacro(MacroName, TargetInfo::getTypeName(Ty));
+}
+
+static void DefineTypeWidth(llvm::StringRef MacroName, TargetInfo::IntType Ty,
+                            const TargetInfo &TI, MacroBuilder &Builder) {
+  Builder.defineMacro(MacroName, llvm::Twine(TI.getTypeWidth(Ty)));
+}
+
+static void DefineExactWidthIntType(TargetInfo::IntType Ty, 
+                               const TargetInfo &TI, MacroBuilder &Builder) {
+  int TypeWidth = TI.getTypeWidth(Ty);
+  DefineType("__INT" + llvm::Twine(TypeWidth) + "_TYPE__", Ty, Builder);
+
+  llvm::StringRef ConstSuffix(TargetInfo::getTypeConstantSuffix(Ty));
+  if (!ConstSuffix.empty())
+    Builder.defineMacro("__INT" + llvm::Twine(TypeWidth) + "_C_SUFFIX__",
+                        ConstSuffix);
+}
+
+static void InitializePredefinedMacros(const TargetInfo &TI,
+                                       const LangOptions &LangOpts,
+                                       const FrontendOptions &FEOpts,
+                                       MacroBuilder &Builder) {
+  // Compiler version introspection macros.
+  Builder.defineMacro("__llvm__");  // LLVM Backend
+  Builder.defineMacro("__clang__"); // Clang Frontend
+
+  // Currently claim to be compatible with GCC 4.2.1-5621.
+  Builder.defineMacro("__GNUC_MINOR__", "2");
+  Builder.defineMacro("__GNUC_PATCHLEVEL__", "1");
+  Builder.defineMacro("__GNUC__", "4");
+  Builder.defineMacro("__GXX_ABI_VERSION", "1002");
+  Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible Clang Compiler\"");
+
+  // Initialize language-specific preprocessor defines.
+
+  // These should all be defined in the preprocessor according to the
+  // current language configuration.
+  if (!LangOpts.Microsoft)
+    Builder.defineMacro("__STDC__");
+  if (LangOpts.AsmPreprocessor)
+    Builder.defineMacro("__ASSEMBLER__");
+
+  if (!LangOpts.CPlusPlus) {
+    if (LangOpts.C99)
+      Builder.defineMacro("__STDC_VERSION__", "199901L");
+    else if (!LangOpts.GNUMode && LangOpts.Digraphs)
+      Builder.defineMacro("__STDC_VERSION__", "199409L");
+  }
+
+  // Standard conforming mode?
+  if (!LangOpts.GNUMode)
+    Builder.defineMacro("__STRICT_ANSI__");
+
+  if (LangOpts.CPlusPlus0x)
+    Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__");
+
+  if (LangOpts.Freestanding)
+    Builder.defineMacro("__STDC_HOSTED__", "0");
+  else
+    Builder.defineMacro("__STDC_HOSTED__");
+
+  if (LangOpts.ObjC1) {
+    Builder.defineMacro("__OBJC__");
+    if (LangOpts.ObjCNonFragileABI) {
+      Builder.defineMacro("__OBJC2__");
+      Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS");
+    }
+
+    if (LangOpts.getGCMode() != LangOptions::NonGC)
+      Builder.defineMacro("__OBJC_GC__");
+
+    if (LangOpts.NeXTRuntime)
+      Builder.defineMacro("__NEXT_RUNTIME__");
+  }
+
+  // darwin_constant_cfstrings controls this. This is also dependent
+  // on other things like the runtime I believe.  This is set even for C code.
+  Builder.defineMacro("__CONSTANT_CFSTRINGS__");
+
+  if (LangOpts.ObjC2)
+    Builder.defineMacro("OBJC_NEW_PROPERTIES");
+
+  if (LangOpts.PascalStrings)
+    Builder.defineMacro("__PASCAL_STRINGS__");
+
+  if (LangOpts.Blocks) {
+    Builder.defineMacro("__block", "__attribute__((__blocks__(byref)))");
+    Builder.defineMacro("__BLOCKS__");
+  }
+
+  if (LangOpts.Exceptions)
+    Builder.defineMacro("__EXCEPTIONS");
+
+  if (LangOpts.CPlusPlus) {
+    Builder.defineMacro("__DEPRECATED");
+    Builder.defineMacro("__GNUG__", "4");
+    Builder.defineMacro("__GXX_WEAK__");
+    if (LangOpts.GNUMode)
+      Builder.defineMacro("__cplusplus");
+    else
+      // C++ [cpp.predefined]p1:
+      //   The name_ _cplusplusis defined to the value199711Lwhen compiling a
+      //   C++ translation unit.
+      Builder.defineMacro("__cplusplus", "199711L");
+    Builder.defineMacro("__private_extern__", "extern");
+    // Ugly hack to work with GNU libstdc++.
+    Builder.defineMacro("_GNU_SOURCE");
+  }
+
+  if (LangOpts.Microsoft) {
+    // Filter out some microsoft extensions when trying to parse in ms-compat
+    // mode.
+    Builder.defineMacro("__int8", "__INT8_TYPE__");
+    Builder.defineMacro("__int16", "__INT16_TYPE__");
+    Builder.defineMacro("__int32", "__INT32_TYPE__");
+    Builder.defineMacro("__int64", "__INT64_TYPE__");
+    // Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however
+    // VC++ appears to only like __FUNCTION__.
+    Builder.defineMacro("__PRETTY_FUNCTION__", "__FUNCTION__");
+    // Work around some issues with Visual C++ headerws.
+    if (LangOpts.CPlusPlus) {
+      // Since we define wchar_t in C++ mode.
+      Builder.defineMacro("_WCHAR_T_DEFINED");
+      Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED");
+      // FIXME:  This should be temporary until we have a __pragma
+      // solution, to avoid some errors flagged in VC++ headers.
+      Builder.defineMacro("_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES", "0");
+    }
+  }
+
+  if (LangOpts.Optimize)
+    Builder.defineMacro("__OPTIMIZE__");
+  if (LangOpts.OptimizeSize)
+    Builder.defineMacro("__OPTIMIZE_SIZE__");
+
+  // Initialize target-specific preprocessor defines.
+
+  // Define type sizing macros based on the target properties.
+  assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
+  Builder.defineMacro("__CHAR_BIT__", "8");
+
+  DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Builder);
+  DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder);
+  DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder);
+  DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder);
+  DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder);
+  DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder);
+  DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
+
+  DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder);
+  DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Builder);
+  DefineTypeWidth("__INTMAX_WIDTH__",  TI.getIntMaxType(), TI, Builder);
+  DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Builder);
+  DefineTypeWidth("__PTRDIFF_WIDTH__", TI.getPtrDiffType(0), TI, Builder);
+  DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Builder);
+  DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Builder);
+  DefineType("__SIZE_TYPE__", TI.getSizeType(), Builder);
+  DefineTypeWidth("__SIZE_WIDTH__", TI.getSizeType(), TI, Builder);
+  DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder);
+  DefineTypeWidth("__WCHAR_WIDTH__", TI.getWCharType(), TI, Builder);
+  DefineType("__WINT_TYPE__", TI.getWIntType(), Builder);
+  DefineTypeWidth("__WINT_WIDTH__", TI.getWIntType(), TI, Builder);
+  DefineTypeWidth("__SIG_ATOMIC_WIDTH__", TI.getSigAtomicType(), TI, Builder);
+
+  DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat());
+  DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat());
+  DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat());
+
+  // Define a __POINTER_WIDTH__ macro for stdint.h.
+  Builder.defineMacro("__POINTER_WIDTH__",
+                      llvm::Twine((int)TI.getPointerWidth(0)));
+
+  if (!LangOpts.CharIsSigned)
+    Builder.defineMacro("__CHAR_UNSIGNED__");
+
+  // Define exact-width integer types for stdint.h
+  Builder.defineMacro("__INT" + llvm::Twine(TI.getCharWidth()) + "_TYPE__",
+                      "char");
+
+  if (TI.getShortWidth() > TI.getCharWidth())
+    DefineExactWidthIntType(TargetInfo::SignedShort, TI, Builder);
+
+  if (TI.getIntWidth() > TI.getShortWidth())
+    DefineExactWidthIntType(TargetInfo::SignedInt, TI, Builder);
+
+  if (TI.getLongWidth() > TI.getIntWidth())
+    DefineExactWidthIntType(TargetInfo::SignedLong, TI, Builder);
+
+  if (TI.getLongLongWidth() > TI.getLongWidth())
+    DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder);
+
+  // Add __builtin_va_list typedef.
+  Builder.append(TI.getVAListDeclaration());
+
+  if (const char *Prefix = TI.getUserLabelPrefix())
+    Builder.defineMacro("__USER_LABEL_PREFIX__", Prefix);
+
+  // Build configuration options.  FIXME: these should be controlled by
+  // command line options or something.
+  Builder.defineMacro("__FINITE_MATH_ONLY__", "0");
+
+  if (LangOpts.GNUInline)
+    Builder.defineMacro("__GNUC_GNU_INLINE__");
+  else
+    Builder.defineMacro("__GNUC_STDC_INLINE__");
+
+  if (LangOpts.NoInline)
+    Builder.defineMacro("__NO_INLINE__");
+
+  if (unsigned PICLevel = LangOpts.PICLevel) {
+    Builder.defineMacro("__PIC__", llvm::Twine(PICLevel));
+    Builder.defineMacro("__pic__", llvm::Twine(PICLevel));
+  }
+
+  // Macros to control C99 numerics and <float.h>
+  Builder.defineMacro("__FLT_EVAL_METHOD__", "0");
+  Builder.defineMacro("__FLT_RADIX__", "2");
+  int Dig = PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36);
+  Builder.defineMacro("__DECIMAL_DIG__", llvm::Twine(Dig));
+
+  if (LangOpts.getStackProtectorMode() == LangOptions::SSPOn)
+    Builder.defineMacro("__SSP__");
+  else if (LangOpts.getStackProtectorMode() == LangOptions::SSPReq)
+    Builder.defineMacro("__SSP_ALL__", "2");
+
+  if (FEOpts.ProgramAction == frontend::RewriteObjC)
+    Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
+  // Get other target #defines.
+  TI.getTargetDefines(LangOpts, Builder);
+}
+
+// Initialize the remapping of files to alternative contents, e.g.,
+// those specified through other files.
+static void InitializeFileRemapping(Diagnostic &Diags,
+                                    SourceManager &SourceMgr,
+                                    FileManager &FileMgr,
+                                    const PreprocessorOptions &InitOpts) {
+  // Remap files in the source manager (with buffers).
+  for (PreprocessorOptions::remapped_file_buffer_iterator
+         Remap = InitOpts.remapped_file_buffer_begin(),
+         RemapEnd = InitOpts.remapped_file_buffer_end();
+       Remap != RemapEnd;
+       ++Remap) {
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+                                                Remap->second->getBufferSize(),
+                                                       0);
+    if (!FromFile) {
+      Diags.Report(diag::err_fe_remap_missing_from_file)
+        << Remap->first;
+      continue;
+    }
+
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    SourceMgr.overrideFileContents(FromFile, Remap->second);
+  }
+
+  // Remap files in the source manager (with other files).
+  for (PreprocessorOptions::remapped_file_iterator
+       Remap = InitOpts.remapped_file_begin(),
+       RemapEnd = InitOpts.remapped_file_end();
+       Remap != RemapEnd;
+       ++Remap) {
+    // Find the file that we're mapping to.
+    const FileEntry *ToFile = FileMgr.getFile(Remap->second);
+    if (!ToFile) {
+      Diags.Report(diag::err_fe_remap_missing_to_file)
+      << Remap->first << Remap->second;
+      continue;
+    }
+    
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+                                                       ToFile->getSize(),
+                                                       0);
+    if (!FromFile) {
+      Diags.Report(diag::err_fe_remap_missing_from_file)
+      << Remap->first;
+      continue;
+    }
+    
+    // Load the contents of the file we're mapping to.
+    std::string ErrorStr;
+    const llvm::MemoryBuffer *Buffer
+    = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
+    if (!Buffer) {
+      Diags.Report(diag::err_fe_error_opening)
+      << Remap->second << ErrorStr;
+      continue;
+    }
+    
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    SourceMgr.overrideFileContents(FromFile, Buffer);
+  }
+}
+
+/// InitializePreprocessor - Initialize the preprocessor getting it and the
+/// environment ready to process a single file. This returns true on error.
+///
+void clang::InitializePreprocessor(Preprocessor &PP,
+                                   const PreprocessorOptions &InitOpts,
+                                   const HeaderSearchOptions &HSOpts,
+                                   const FrontendOptions &FEOpts) {
+  std::string PredefineBuffer;
+  PredefineBuffer.reserve(4080);
+  llvm::raw_string_ostream Predefines(PredefineBuffer);
+  MacroBuilder Builder(Predefines);
+
+  InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
+                          PP.getFileManager(), InitOpts);
+
+  Builder.append("# 1 \"<built-in>\" 3");
+
+  // Install things like __POWERPC__, __GNUC__, etc into the macro table.
+  if (InitOpts.UsePredefines)
+    InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
+                               FEOpts, Builder);
+
+  // Add on the predefines from the driver.  Wrap in a #line directive to report
+  // that they come from the command line.
+  Builder.append("# 1 \"<command line>\" 1");
+
+  // Process #define's and #undef's in the order they are given.
+  for (unsigned i = 0, e = InitOpts.Macros.size(); i != e; ++i) {
+    if (InitOpts.Macros[i].second)  // isUndef
+      Builder.undefineMacro(InitOpts.Macros[i].first);
+    else
+      DefineBuiltinMacro(Builder, InitOpts.Macros[i].first,
+                         PP.getDiagnostics());
+  }
+
+  // If -imacros are specified, include them now.  These are processed before
+  // any -include directives.
+  for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
+    AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]);
+
+  // Process -include directives.
+  for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
+    const std::string &Path = InitOpts.Includes[i];
+    if (Path == InitOpts.ImplicitPTHInclude)
+      AddImplicitIncludePTH(Builder, PP, Path);
+    else
+      AddImplicitInclude(Builder, Path);
+  }
+
+  // Exit the command line and go back to <built-in> (2 is LC_LEAVE).
+  Builder.append("# 1 \"<built-in>\" 2");
+
+  // Copy PredefinedBuffer into the Preprocessor.
+  PP.setPredefines(Predefines.str());
+
+  // Initialize the header search object.
+  ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts,
+                           PP.getLangOptions(),
+                           PP.getTargetInfo().getTriple());
+}
diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp
new file mode 100644
index 0000000..ed0ea1f
--- /dev/null
+++ b/lib/Frontend/LangStandards.cpp
@@ -0,0 +1,44 @@
+//===--- LangStandards.cpp - Language Standard Definitions ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/LangStandard.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+using namespace clang::frontend;
+
+#define LANGSTANDARD(id, name, desc, features) \
+  static const LangStandard Lang_##id = { name, desc, features };
+#include "clang/Frontend/LangStandards.def"
+
+const LangStandard &LangStandard::getLangStandardForKind(Kind K) {
+  switch (K) {
+  default:
+    llvm_unreachable("Invalid language kind!");
+  case lang_unspecified:
+    llvm::llvm_report_error("getLangStandardForKind() on unspecified kind");
+#define LANGSTANDARD(id, name, desc, features) \
+    case lang_##id: return Lang_##id;
+#include "clang/Frontend/LangStandards.def"
+  }
+}
+
+const LangStandard *LangStandard::getLangStandardForName(llvm::StringRef Name) {
+  Kind K = llvm::StringSwitch<Kind>(Name)
+#define LANGSTANDARD(id, name, desc, features) \
+    .Case(name, lang_##id)
+#include "clang/Frontend/LangStandards.def"
+    .Default(lang_unspecified);
+  if (K == lang_unspecified)
+    return 0;
+
+  return &getLangStandardForKind(K);
+}
+
+
diff --git a/lib/Frontend/Makefile b/lib/Frontend/Makefile
new file mode 100644
index 0000000..a630b01
--- /dev/null
+++ b/lib/Frontend/Makefile
@@ -0,0 +1,17 @@
+##===- clang/lib/Frontend/Makefile -------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME := clangFrontend
+BUILD_ARCHIVE = 1
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
new file mode 100644
index 0000000..9ab3b7a
--- /dev/null
+++ b/lib/Frontend/PCHReader.cpp
@@ -0,0 +1,2816 @@
+//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- 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 PCHReader class, which reads a precompiled header.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/System/Path.h"
+#include <algorithm>
+#include <iterator>
+#include <cstdio>
+#include <sys/stat.h>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// PCH reader validator implementation
+//===----------------------------------------------------------------------===//
+
+PCHReaderListener::~PCHReaderListener() {}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
+  const LangOptions &PPLangOpts = PP.getLangOptions();
+#define PARSE_LANGOPT_BENIGN(Option)
+#define PARSE_LANGOPT_IMPORTANT(Option, DiagID)                    \
+  if (PPLangOpts.Option != LangOpts.Option) {                      \
+    Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option;   \
+    return true;                                                   \
+  }
+
+  PARSE_LANGOPT_BENIGN(Trigraphs);
+  PARSE_LANGOPT_BENIGN(BCPLComment);
+  PARSE_LANGOPT_BENIGN(DollarIdents);
+  PARSE_LANGOPT_BENIGN(AsmPreprocessor);
+  PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+  PARSE_LANGOPT_BENIGN(ImplicitInt);
+  PARSE_LANGOPT_BENIGN(Digraphs);
+  PARSE_LANGOPT_BENIGN(HexFloats);
+  PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
+  PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+  PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
+  PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
+  PARSE_LANGOPT_BENIGN(CXXOperatorName);
+  PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
+  PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
+  PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
+  PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2);
+  PARSE_LANGOPT_BENIGN(PascalStrings);
+  PARSE_LANGOPT_BENIGN(WritableStrings);
+  PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
+                          diag::warn_pch_lax_vector_conversions);
+  PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
+  PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
+  PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
+  PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
+  PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
+  PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
+                          diag::warn_pch_thread_safe_statics);
+  PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads);
+  PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
+  PARSE_LANGOPT_BENIGN(EmitAllDecls);
+  PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
+  PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
+  PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
+                          diag::warn_pch_heinous_extensions);
+  // FIXME: Most of the options below are benign if the macro wasn't
+  // used. Unfortunately, this means that a PCH compiled without
+  // optimization can't be used with optimization turned on, even
+  // though the only thing that changes is whether __OPTIMIZE__ was
+  // defined... but if __OPTIMIZE__ never showed up in the header, it
+  // doesn't matter. We could consider making this some special kind
+  // of check.
+  PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
+  PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
+  PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
+  PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
+  PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
+  PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
+  PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
+  PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+  PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
+  if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
+    Reader.Diag(diag::warn_pch_gc_mode)
+      << LangOpts.getGCMode() << PPLangOpts.getGCMode();
+    return true;
+  }
+  PARSE_LANGOPT_BENIGN(getVisibilityMode());
+  PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(),
+                          diag::warn_pch_stack_protector);
+  PARSE_LANGOPT_BENIGN(InstantiationDepth);
+  PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
+  PARSE_LANGOPT_BENIGN(CatchUndefined);
+  PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
+#undef PARSE_LANGOPT_IRRELEVANT
+#undef PARSE_LANGOPT_BENIGN
+
+  return false;
+}
+
+bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
+  if (Triple == PP.getTargetInfo().getTriple().str())
+    return false;
+
+  Reader.Diag(diag::warn_pch_target_triple)
+    << Triple << PP.getTargetInfo().getTriple().str();
+  return true;
+}
+
+bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
+                                        FileID PCHBufferID,
+                                        llvm::StringRef OriginalFileName,
+                                        std::string &SuggestedPredefines) {
+  // We are in the context of an implicit include, so the predefines buffer will
+  // have a #include entry for the PCH file itself (as normalized by the
+  // preprocessor initialization). Find it and skip over it in the checking
+  // below.
+  llvm::SmallString<256> PCHInclude;
+  PCHInclude += "#include \"";
+  PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+  PCHInclude += "\"\n";
+  std::pair<llvm::StringRef,llvm::StringRef> Split =
+    llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
+  llvm::StringRef Left =  Split.first, Right = Split.second;
+  assert(Left != PP.getPredefines() && "Missing PCH include entry!");
+
+  // If the predefines is equal to the joined left and right halves, we're done!
+  if (Left.size() + Right.size() == PCHPredef.size() &&
+      PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
+    return false;
+
+  SourceManager &SourceMgr = PP.getSourceManager();
+
+  // The predefines buffers are different. Determine what the differences are,
+  // and whether they require us to reject the PCH file.
+  llvm::SmallVector<llvm::StringRef, 8> PCHLines;
+  PCHPredef.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+  llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
+  Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+  Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+  // Sort both sets of predefined buffer lines, since we allow some extra
+  // definitions and they may appear at any point in the output.
+  std::sort(CmdLineLines.begin(), CmdLineLines.end());
+  std::sort(PCHLines.begin(), PCHLines.end());
+
+  // Determine which predefines that were used to build the PCH file are missing
+  // from the command line.
+  std::vector<llvm::StringRef> MissingPredefines;
+  std::set_difference(PCHLines.begin(), PCHLines.end(),
+                      CmdLineLines.begin(), CmdLineLines.end(),
+                      std::back_inserter(MissingPredefines));
+
+  bool MissingDefines = false;
+  bool ConflictingDefines = false;
+  for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
+    llvm::StringRef Missing = MissingPredefines[I];
+    if (!Missing.startswith("#define ")) {
+      Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+      return true;
+    }
+
+    // This is a macro definition. Determine the name of the macro we're
+    // defining.
+    std::string::size_type StartOfMacroName = strlen("#define ");
+    std::string::size_type EndOfMacroName
+      = Missing.find_first_of("( \n\r", StartOfMacroName);
+    assert(EndOfMacroName != std::string::npos &&
+           "Couldn't find the end of the macro name");
+    llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
+
+    // Determine whether this macro was given a different definition on the
+    // command line.
+    std::string MacroDefStart = "#define " + MacroName.str();
+    std::string::size_type MacroDefLen = MacroDefStart.size();
+    llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos
+      = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
+                         MacroDefStart);
+    for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
+      if (!ConflictPos->startswith(MacroDefStart)) {
+        // Different macro; we're done.
+        ConflictPos = CmdLineLines.end();
+        break;
+      }
+
+      assert(ConflictPos->size() > MacroDefLen &&
+             "Invalid #define in predefines buffer?");
+      if ((*ConflictPos)[MacroDefLen] != ' ' &&
+          (*ConflictPos)[MacroDefLen] != '(')
+        continue; // Longer macro name; keep trying.
+
+      // We found a conflicting macro definition.
+      break;
+    }
+
+    if (ConflictPos != CmdLineLines.end()) {
+      Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
+          << MacroName;
+
+      // Show the definition of this macro within the PCH file.
+      llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+      assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+      SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
+        .getFileLocWithOffset(Offset);
+      Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
+
+      ConflictingDefines = true;
+      continue;
+    }
+
+    // If the macro doesn't conflict, then we'll just pick up the macro
+    // definition from the PCH file. Warn the user that they made a mistake.
+    if (ConflictingDefines)
+      continue; // Don't complain if there are already conflicting defs
+
+    if (!MissingDefines) {
+      Reader.Diag(diag::warn_cmdline_missing_macro_defs);
+      MissingDefines = true;
+    }
+
+    // Show the definition of this macro within the PCH file.
+    llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+    assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+    SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
+      .getFileLocWithOffset(Offset);
+    Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
+  }
+
+  if (ConflictingDefines)
+    return true;
+
+  // Determine what predefines were introduced based on command-line
+  // parameters that were not present when building the PCH
+  // file. Extra #defines are okay, so long as the identifiers being
+  // defined were not used within the precompiled header.
+  std::vector<llvm::StringRef> ExtraPredefines;
+  std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
+                      PCHLines.begin(), PCHLines.end(),
+                      std::back_inserter(ExtraPredefines));
+  for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
+    llvm::StringRef &Extra = ExtraPredefines[I];
+    if (!Extra.startswith("#define ")) {
+      Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+      return true;
+    }
+
+    // This is an extra macro definition. Determine the name of the
+    // macro we're defining.
+    std::string::size_type StartOfMacroName = strlen("#define ");
+    std::string::size_type EndOfMacroName
+      = Extra.find_first_of("( \n\r", StartOfMacroName);
+    assert(EndOfMacroName != std::string::npos &&
+           "Couldn't find the end of the macro name");
+    llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
+
+    // Check whether this name was used somewhere in the PCH file. If
+    // so, defining it as a macro could change behavior, so we reject
+    // the PCH file.
+    if (IdentifierInfo *II = Reader.get(MacroName)) {
+      Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
+      return true;
+    }
+
+    // Add this definition to the suggested predefines buffer.
+    SuggestedPredefines += Extra;
+    SuggestedPredefines += '\n';
+  }
+
+  // If we get here, it's because the predefines buffer had compatible
+  // contents. Accept the PCH file.
+  return false;
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+}
+
+void PCHValidator::ReadCounter(unsigned Value) {
+  PP.setCounterValue(Value);
+}
+
+//===----------------------------------------------------------------------===//
+// PCH reader implementation
+//===----------------------------------------------------------------------===//
+
+PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
+                     const char *isysroot)
+  : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
+    FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
+    SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),
+    IdentifierTableData(0), IdentifierLookupTable(0),
+    IdentifierOffsets(0),
+    MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
+    TotalSelectorsInMethodPool(0), SelectorOffsets(0),
+    TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
+    NumStatHits(0), NumStatMisses(0),
+    NumSLocEntriesRead(0), NumStatementsRead(0),
+    NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
+    NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
+    CurrentlyLoadingTypeOrDecl(0) {
+  RelocatablePCH = false;
+}
+
+PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
+                     Diagnostic &Diags, const char *isysroot)
+  : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
+    SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
+    IdentifierTableData(0), IdentifierLookupTable(0),
+    IdentifierOffsets(0),
+    MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
+    TotalSelectorsInMethodPool(0), SelectorOffsets(0),
+    TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
+    NumStatHits(0), NumStatMisses(0),
+    NumSLocEntriesRead(0), NumStatementsRead(0),
+    NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
+    NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
+    CurrentlyLoadingTypeOrDecl(0) {
+  RelocatablePCH = false;
+}
+
+PCHReader::~PCHReader() {}
+
+Expr *PCHReader::ReadDeclExpr() {
+  return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
+}
+
+Expr *PCHReader::ReadTypeExpr() {
+  return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
+}
+
+
+namespace {
+class PCHMethodPoolLookupTrait {
+  PCHReader &Reader;
+
+public:
+  typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
+
+  typedef Selector external_key_type;
+  typedef external_key_type internal_key_type;
+
+  explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
+
+  static bool EqualKey(const internal_key_type& a,
+                       const internal_key_type& b) {
+    return a == b;
+  }
+
+  static unsigned ComputeHash(Selector Sel) {
+    unsigned N = Sel.getNumArgs();
+    if (N == 0)
+      ++N;
+    unsigned R = 5381;
+    for (unsigned I = 0; I != N; ++I)
+      if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
+        R = llvm::HashString(II->getName(), R);
+    return R;
+  }
+
+  // This hopefully will just get inlined and removed by the optimizer.
+  static const internal_key_type&
+  GetInternalKey(const external_key_type& x) { return x; }
+
+  static std::pair<unsigned, unsigned>
+  ReadKeyDataLength(const unsigned char*& d) {
+    using namespace clang::io;
+    unsigned KeyLen = ReadUnalignedLE16(d);
+    unsigned DataLen = ReadUnalignedLE16(d);
+    return std::make_pair(KeyLen, DataLen);
+  }
+
+  internal_key_type ReadKey(const unsigned char* d, unsigned) {
+    using namespace clang::io;
+    SelectorTable &SelTable = Reader.getContext()->Selectors;
+    unsigned N = ReadUnalignedLE16(d);
+    IdentifierInfo *FirstII
+      = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
+    if (N == 0)
+      return SelTable.getNullarySelector(FirstII);
+    else if (N == 1)
+      return SelTable.getUnarySelector(FirstII);
+
+    llvm::SmallVector<IdentifierInfo *, 16> Args;
+    Args.push_back(FirstII);
+    for (unsigned I = 1; I != N; ++I)
+      Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
+
+    return SelTable.getSelector(N, Args.data());
+  }
+
+  data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
+    using namespace clang::io;
+    unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+    unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
+    data_type Result;
+
+    // Load instance methods
+    ObjCMethodList *Prev = 0;
+    for (unsigned I = 0; I != NumInstanceMethods; ++I) {
+      ObjCMethodDecl *Method
+        = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
+      if (!Result.first.Method) {
+        // This is the first method, which is the easy case.
+        Result.first.Method = Method;
+        Prev = &Result.first;
+        continue;
+      }
+
+      Prev->Next = new ObjCMethodList(Method, 0);
+      Prev = Prev->Next;
+    }
+
+    // Load factory methods
+    Prev = 0;
+    for (unsigned I = 0; I != NumFactoryMethods; ++I) {
+      ObjCMethodDecl *Method
+        = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
+      if (!Result.second.Method) {
+        // This is the first method, which is the easy case.
+        Result.second.Method = Method;
+        Prev = &Result.second;
+        continue;
+      }
+
+      Prev->Next = new ObjCMethodList(Method, 0);
+      Prev = Prev->Next;
+    }
+
+    return Result;
+  }
+};
+
+} // end anonymous namespace
+
+/// \brief The on-disk hash table used for the global method pool.
+typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
+  PCHMethodPoolLookupTable;
+
+namespace {
+class PCHIdentifierLookupTrait {
+  PCHReader &Reader;
+
+  // If we know the IdentifierInfo in advance, it is here and we will
+  // not build a new one. Used when deserializing information about an
+  // identifier that was constructed before the PCH file was read.
+  IdentifierInfo *KnownII;
+
+public:
+  typedef IdentifierInfo * data_type;
+
+  typedef const std::pair<const char*, unsigned> external_key_type;
+
+  typedef external_key_type internal_key_type;
+
+  explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
+    : Reader(Reader), KnownII(II) { }
+
+  static bool EqualKey(const internal_key_type& a,
+                       const internal_key_type& b) {
+    return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
+                                  : false;
+  }
+
+  static unsigned ComputeHash(const internal_key_type& a) {
+    return llvm::HashString(llvm::StringRef(a.first, a.second));
+  }
+
+  // This hopefully will just get inlined and removed by the optimizer.
+  static const internal_key_type&
+  GetInternalKey(const external_key_type& x) { return x; }
+
+  static std::pair<unsigned, unsigned>
+  ReadKeyDataLength(const unsigned char*& d) {
+    using namespace clang::io;
+    unsigned DataLen = ReadUnalignedLE16(d);
+    unsigned KeyLen = ReadUnalignedLE16(d);
+    return std::make_pair(KeyLen, DataLen);
+  }
+
+  static std::pair<const char*, unsigned>
+  ReadKey(const unsigned char* d, unsigned n) {
+    assert(n >= 2 && d[n-1] == '\0');
+    return std::make_pair((const char*) d, n-1);
+  }
+
+  IdentifierInfo *ReadData(const internal_key_type& k,
+                           const unsigned char* d,
+                           unsigned DataLen) {
+    using namespace clang::io;
+    pch::IdentID ID = ReadUnalignedLE32(d);
+    bool IsInteresting = ID & 0x01;
+
+    // Wipe out the "is interesting" bit.
+    ID = ID >> 1;
+
+    if (!IsInteresting) {
+      // For unintersting identifiers, just build the IdentifierInfo
+      // and associate it with the persistent ID.
+      IdentifierInfo *II = KnownII;
+      if (!II)
+        II = &Reader.getIdentifierTable().CreateIdentifierInfo(
+                                                 k.first, k.first + k.second);
+      Reader.SetIdentifierInfo(ID, II);
+      return II;
+    }
+
+    unsigned Bits = ReadUnalignedLE16(d);
+    bool CPlusPlusOperatorKeyword = Bits & 0x01;
+    Bits >>= 1;
+    bool Poisoned = Bits & 0x01;
+    Bits >>= 1;
+    bool ExtensionToken = Bits & 0x01;
+    Bits >>= 1;
+    bool hasMacroDefinition = Bits & 0x01;
+    Bits >>= 1;
+    unsigned ObjCOrBuiltinID = Bits & 0x3FF;
+    Bits >>= 10;
+
+    assert(Bits == 0 && "Extra bits in the identifier?");
+    DataLen -= 6;
+
+    // Build the IdentifierInfo itself and link the identifier ID with
+    // the new IdentifierInfo.
+    IdentifierInfo *II = KnownII;
+    if (!II)
+      II = &Reader.getIdentifierTable().CreateIdentifierInfo(
+                                                 k.first, k.first + k.second);
+    Reader.SetIdentifierInfo(ID, II);
+
+    // Set or check the various bits in the IdentifierInfo structure.
+    // FIXME: Load token IDs lazily, too?
+    II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+    assert(II->isExtensionToken() == ExtensionToken &&
+           "Incorrect extension token flag");
+    (void)ExtensionToken;
+    II->setIsPoisoned(Poisoned);
+    assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
+           "Incorrect C++ operator keyword flag");
+    (void)CPlusPlusOperatorKeyword;
+
+    // If this identifier is a macro, deserialize the macro
+    // definition.
+    if (hasMacroDefinition) {
+      uint32_t Offset = ReadUnalignedLE32(d);
+      Reader.ReadMacroRecord(Offset);
+      DataLen -= 4;
+    }
+
+    // Read all of the declarations visible at global scope with this
+    // name.
+    if (Reader.getContext() == 0) return II;
+    if (DataLen > 0) {
+      llvm::SmallVector<uint32_t, 4> DeclIDs;
+      for (; DataLen > 0; DataLen -= 4)
+        DeclIDs.push_back(ReadUnalignedLE32(d));
+      Reader.SetGloballyVisibleDecls(II, DeclIDs);
+    }
+
+    return II;
+  }
+};
+
+} // end anonymous namespace
+
+/// \brief The on-disk hash table used to contain information about
+/// all of the identifiers in the program.
+typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
+  PCHIdentifierLookupTable;
+
+bool PCHReader::Error(const char *Msg) {
+  unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
+  Diag(DiagID);
+  return true;
+}
+
+/// \brief Check the contents of the predefines buffer against the
+/// contents of the predefines buffer used to build the PCH file.
+///
+/// The contents of the two predefines buffers should be the same. If
+/// not, then some command-line option changed the preprocessor state
+/// and we must reject the PCH file.
+///
+/// \param PCHPredef The start of the predefines buffer in the PCH
+/// file.
+///
+/// \param PCHPredefLen The length of the predefines buffer in the PCH
+/// file.
+///
+/// \param PCHBufferID The FileID for the PCH predefines buffer.
+///
+/// \returns true if there was a mismatch (in which case the PCH file
+/// should be ignored), or false otherwise.
+bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
+                                      FileID PCHBufferID) {
+  if (Listener)
+    return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
+                                          ActualOriginalFileName,
+                                          SuggestedPredefines);
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Source Manager Deserialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Read the line table in the source manager block.
+/// \returns true if ther was an error.
+bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
+  unsigned Idx = 0;
+  LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+  // Parse the file names
+  std::map<int, int> FileIDs;
+  for (int I = 0, N = Record[Idx++]; I != N; ++I) {
+    // Extract the file name
+    unsigned FilenameLen = Record[Idx++];
+    std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
+    Idx += FilenameLen;
+    MaybeAddSystemRootToFilename(Filename);
+    FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
+                                                  Filename.size());
+  }
+
+  // Parse the line entries
+  std::vector<LineEntry> Entries;
+  while (Idx < Record.size()) {
+    int FID = FileIDs[Record[Idx++]];
+
+    // Extract the line entries
+    unsigned NumEntries = Record[Idx++];
+    Entries.clear();
+    Entries.reserve(NumEntries);
+    for (unsigned I = 0; I != NumEntries; ++I) {
+      unsigned FileOffset = Record[Idx++];
+      unsigned LineNo = Record[Idx++];
+      int FilenameID = Record[Idx++];
+      SrcMgr::CharacteristicKind FileKind
+        = (SrcMgr::CharacteristicKind)Record[Idx++];
+      unsigned IncludeOffset = Record[Idx++];
+      Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
+                                       FileKind, IncludeOffset));
+    }
+    LineTable.AddEntry(FID, Entries);
+  }
+
+  return false;
+}
+
+namespace {
+
+class PCHStatData {
+public:
+  const bool hasStat;
+  const ino_t ino;
+  const dev_t dev;
+  const mode_t mode;
+  const time_t mtime;
+  const off_t size;
+
+  PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
+  : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
+
+  PCHStatData()
+    : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
+};
+
+class PCHStatLookupTrait {
+ public:
+  typedef const char *external_key_type;
+  typedef const char *internal_key_type;
+
+  typedef PCHStatData data_type;
+
+  static unsigned ComputeHash(const char *path) {
+    return llvm::HashString(path);
+  }
+
+  static internal_key_type GetInternalKey(const char *path) { return path; }
+
+  static bool EqualKey(internal_key_type a, internal_key_type b) {
+    return strcmp(a, b) == 0;
+  }
+
+  static std::pair<unsigned, unsigned>
+  ReadKeyDataLength(const unsigned char*& d) {
+    unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+    unsigned DataLen = (unsigned) *d++;
+    return std::make_pair(KeyLen + 1, DataLen);
+  }
+
+  static internal_key_type ReadKey(const unsigned char *d, unsigned) {
+    return (const char *)d;
+  }
+
+  static data_type ReadData(const internal_key_type, const unsigned char *d,
+                            unsigned /*DataLen*/) {
+    using namespace clang::io;
+
+    if (*d++ == 1)
+      return data_type();
+
+    ino_t ino = (ino_t) ReadUnalignedLE32(d);
+    dev_t dev = (dev_t) ReadUnalignedLE32(d);
+    mode_t mode = (mode_t) ReadUnalignedLE16(d);
+    time_t mtime = (time_t) ReadUnalignedLE64(d);
+    off_t size = (off_t) ReadUnalignedLE64(d);
+    return data_type(ino, dev, mode, mtime, size);
+  }
+};
+
+/// \brief stat() cache for precompiled headers.
+///
+/// This cache is very similar to the stat cache used by pretokenized
+/// headers.
+class PCHStatCache : public StatSysCallCache {
+  typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
+  CacheTy *Cache;
+
+  unsigned &NumStatHits, &NumStatMisses;
+public:
+  PCHStatCache(const unsigned char *Buckets,
+               const unsigned char *Base,
+               unsigned &NumStatHits,
+               unsigned &NumStatMisses)
+    : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
+    Cache = CacheTy::Create(Buckets, Base);
+  }
+
+  ~PCHStatCache() { delete Cache; }
+
+  int stat(const char *path, struct stat *buf) {
+    // Do the lookup for the file's data in the PCH file.
+    CacheTy::iterator I = Cache->find(path);
+
+    // If we don't get a hit in the PCH file just forward to 'stat'.
+    if (I == Cache->end()) {
+      ++NumStatMisses;
+      return StatSysCallCache::stat(path, buf);
+    }
+
+    ++NumStatHits;
+    PCHStatData Data = *I;
+
+    if (!Data.hasStat)
+      return 1;
+
+    buf->st_ino = Data.ino;
+    buf->st_dev = Data.dev;
+    buf->st_mtime = Data.mtime;
+    buf->st_mode = Data.mode;
+    buf->st_size = Data.size;
+    return 0;
+  }
+};
+} // end anonymous namespace
+
+
+/// \brief Read the source manager block
+PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
+  using namespace SrcMgr;
+
+  // Set the source-location entry cursor to the current position in
+  // the stream. This cursor will be used to read the contents of the
+  // source manager block initially, and then lazily read
+  // source-location entries as needed.
+  SLocEntryCursor = Stream;
+
+  // The stream itself is going to skip over the source manager block.
+  if (Stream.SkipBlock()) {
+    Error("malformed block record in PCH file");
+    return Failure;
+  }
+
+  // Enter the source manager block.
+  if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
+    Error("malformed source manager block record in PCH file");
+    return Failure;
+  }
+
+  RecordData Record;
+  while (true) {
+    unsigned Code = SLocEntryCursor.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (SLocEntryCursor.ReadBlockEnd()) {
+        Error("error at end of Source Manager block in PCH file");
+        return Failure;
+      }
+      return Success;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      SLocEntryCursor.ReadSubBlockID();
+      if (SLocEntryCursor.SkipBlock()) {
+        Error("malformed block record in PCH file");
+        return Failure;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      SLocEntryCursor.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    const char *BlobStart;
+    unsigned BlobLen;
+    Record.clear();
+    switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+
+    case pch::SM_LINE_TABLE:
+      if (ParseLineTable(Record))
+        return Failure;
+      break;
+
+    case pch::SM_HEADER_FILE_INFO: {
+      HeaderFileInfo HFI;
+      HFI.isImport = Record[0];
+      HFI.DirInfo = Record[1];
+      HFI.NumIncludes = Record[2];
+      HFI.ControllingMacroID = Record[3];
+      if (Listener)
+        Listener->ReadHeaderFileInfo(HFI);
+      break;
+    }
+
+    case pch::SM_SLOC_FILE_ENTRY:
+    case pch::SM_SLOC_BUFFER_ENTRY:
+    case pch::SM_SLOC_INSTANTIATION_ENTRY:
+      // Once we hit one of the source location entries, we're done.
+      return Success;
+    }
+  }
+}
+
+/// \brief Read in the source location entry with the given ID.
+PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
+  if (ID == 0)
+    return Success;
+
+  if (ID > TotalNumSLocEntries) {
+    Error("source location entry ID out-of-range for PCH file");
+    return Failure;
+  }
+
+  ++NumSLocEntriesRead;
+  SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
+  unsigned Code = SLocEntryCursor.ReadCode();
+  if (Code == llvm::bitc::END_BLOCK ||
+      Code == llvm::bitc::ENTER_SUBBLOCK ||
+      Code == llvm::bitc::DEFINE_ABBREV) {
+    Error("incorrectly-formatted source location entry in PCH file");
+    return Failure;
+  }
+
+  RecordData Record;
+  const char *BlobStart;
+  unsigned BlobLen;
+  switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+  default:
+    Error("incorrectly-formatted source location entry in PCH file");
+    return Failure;
+
+  case pch::SM_SLOC_FILE_ENTRY: {
+    std::string Filename(BlobStart, BlobStart + BlobLen);
+    MaybeAddSystemRootToFilename(Filename);
+    const FileEntry *File = FileMgr.getFile(Filename);
+    if (File == 0) {
+      std::string ErrorStr = "could not find file '";
+      ErrorStr += Filename;
+      ErrorStr += "' referenced by PCH file";
+      Error(ErrorStr.c_str());
+      return Failure;
+    }
+
+    FileID FID = SourceMgr.createFileID(File,
+                                SourceLocation::getFromRawEncoding(Record[1]),
+                                       (SrcMgr::CharacteristicKind)Record[2],
+                                        ID, Record[0]);
+    if (Record[3])
+      const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
+        .setHasLineDirectives();
+
+    break;
+  }
+
+  case pch::SM_SLOC_BUFFER_ENTRY: {
+    const char *Name = BlobStart;
+    unsigned Offset = Record[0];
+    unsigned Code = SLocEntryCursor.ReadCode();
+    Record.clear();
+    unsigned RecCode
+      = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+    assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
+    (void)RecCode;
+    llvm::MemoryBuffer *Buffer
+      = llvm::MemoryBuffer::getMemBuffer(BlobStart,
+                                         BlobStart + BlobLen - 1,
+                                         Name);
+    FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
+
+    if (strcmp(Name, "<built-in>") == 0) {
+      PCHPredefinesBufferID = BufferID;
+      PCHPredefines = BlobStart;
+      PCHPredefinesLen = BlobLen - 1;
+    }
+
+    break;
+  }
+
+  case pch::SM_SLOC_INSTANTIATION_ENTRY: {
+    SourceLocation SpellingLoc
+      = SourceLocation::getFromRawEncoding(Record[1]);
+    SourceMgr.createInstantiationLoc(SpellingLoc,
+                              SourceLocation::getFromRawEncoding(Record[2]),
+                              SourceLocation::getFromRawEncoding(Record[3]),
+                                     Record[4],
+                                     ID,
+                                     Record[0]);
+    break;
+  }
+  }
+
+  return Success;
+}
+
+/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
+/// specified cursor.  Read the abbreviations that are at the top of the block
+/// and then leave the cursor pointing into the block.
+bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
+                                 unsigned BlockID) {
+  if (Cursor.EnterSubBlock(BlockID)) {
+    Error("malformed block record in PCH file");
+    return Failure;
+  }
+
+  while (true) {
+    unsigned Code = Cursor.ReadCode();
+
+    // We expect all abbrevs to be at the start of the block.
+    if (Code != llvm::bitc::DEFINE_ABBREV)
+      return false;
+    Cursor.ReadAbbrevRecord();
+  }
+}
+
+void PCHReader::ReadMacroRecord(uint64_t Offset) {
+  assert(PP && "Forgot to set Preprocessor ?");
+
+  // 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;
+  llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
+  MacroInfo *Macro = 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 PCH file");
+        return;
+      }
+      continue;
+
+    case llvm::bitc::DEFINE_ABBREV:
+      Stream.ReadAbbrevRecord();
+      continue;
+    default: break;
+    }
+
+    // Read a record.
+    Record.clear();
+    pch::PreprocessorRecordTypes RecType =
+      (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
+    switch (RecType) {
+    case pch::PP_MACRO_OBJECT_LIKE:
+    case pch::PP_MACRO_FUNCTION_LIKE: {
+      // If we already have a macro, that means that we've hit the end
+      // of the definition of the macro we were looking for. We're
+      // done.
+      if (Macro)
+        return;
+
+      IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
+      if (II == 0) {
+        Error("macro must have a name in PCH file");
+        return;
+      }
+      SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
+      bool isUsed = Record[2];
+
+      MacroInfo *MI = PP->AllocateMacroInfo(Loc);
+      MI->setIsUsed(isUsed);
+
+      if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
+        // Decode function-like macro info.
+        bool isC99VarArgs = Record[3];
+        bool isGNUVarArgs = Record[4];
+        MacroArgs.clear();
+        unsigned NumArgs = Record[5];
+        for (unsigned i = 0; i != NumArgs; ++i)
+          MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
+
+        // Install function-like macro info.
+        MI->setIsFunctionLike();
+        if (isC99VarArgs) MI->setIsC99Varargs();
+        if (isGNUVarArgs) MI->setIsGNUVarargs();
+        MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
+                            PP->getPreprocessorAllocator());
+      }
+
+      // Finally, install the macro.
+      PP->setMacroInfo(II, MI);
+
+      // Remember that we saw this macro last so that we add the tokens that
+      // form its body to it.
+      Macro = MI;
+      ++NumMacrosRead;
+      break;
+    }
+
+    case pch::PP_TOKEN: {
+      // If we see a TOKEN before a PP_MACRO_*, then the file is
+      // erroneous, just pretend we didn't see this.
+      if (Macro == 0) break;
+
+      Token Tok;
+      Tok.startToken();
+      Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
+      Tok.setLength(Record[1]);
+      if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
+        Tok.setIdentifierInfo(II);
+      Tok.setKind((tok::TokenKind)Record[3]);
+      Tok.setFlag((Token::TokenFlags)Record[4]);
+      Macro->AddTokenToBody(Tok);
+      break;
+    }
+  }
+  }
+}
+
+void PCHReader::ReadDefinedMacros() {
+  // If there was no preprocessor block, do nothing.
+  if (!MacroCursor.getBitStreamReader())
+    return;
+  
+  llvm::BitstreamCursor Cursor = MacroCursor;
+  if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) {
+    Error("malformed preprocessor block record in PCH file");
+    return;
+  }
+  
+  RecordData Record;
+  while (true) {
+    unsigned Code = Cursor.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Cursor.ReadBlockEnd())
+        Error("error at end of preprocessor block in PCH file");
+      return;
+    }
+    
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Cursor.ReadSubBlockID();
+      if (Cursor.SkipBlock()) {
+        Error("malformed block record in PCH file");
+        return;
+      }
+      continue;
+    }
+    
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Cursor.ReadAbbrevRecord();
+      continue;
+    }
+    
+    // Read a record.
+    const char *BlobStart;
+    unsigned BlobLen;
+    Record.clear();
+    switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+        
+    case pch::PP_MACRO_OBJECT_LIKE:
+    case pch::PP_MACRO_FUNCTION_LIKE:
+        DecodeIdentifierInfo(Record[0]);
+      break;
+
+    case pch::PP_TOKEN:
+      // Ignore tokens.
+      break;
+    }
+  }
+}
+
+/// \brief If we are loading a relocatable PCH file, and the filename is
+/// not an absolute path, add the system root to the beginning of the file
+/// name.
+void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
+  // If this is not a relocatable PCH file, there's nothing to do.
+  if (!RelocatablePCH)
+    return;
+
+  if (Filename.empty() || llvm::sys::Path(Filename).isAbsolute())
+    return;
+
+  if (isysroot == 0) {
+    // If no system root was given, default to '/'
+    Filename.insert(Filename.begin(), '/');
+    return;
+  }
+
+  unsigned Length = strlen(isysroot);
+  if (isysroot[Length - 1] != '/')
+    Filename.insert(Filename.begin(), '/');
+
+  Filename.insert(Filename.begin(), isysroot, isysroot + Length);
+}
+
+PCHReader::PCHReadResult
+PCHReader::ReadPCHBlock() {
+  if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
+    Error("malformed block record in PCH file");
+    return Failure;
+  }
+
+  // Read all of the records and blocks for the PCH file.
+  RecordData Record;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Error("error at end of module block in PCH file");
+        return Failure;
+      }
+
+      return Success;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      case pch::DECLTYPES_BLOCK_ID:
+        // We lazily load the decls block, but we want to set up the
+        // DeclsCursor cursor to point into it.  Clone our current bitcode
+        // cursor to it, enter the block and read the abbrevs in that block.
+        // With the main cursor, we just skip over it.
+        DeclsCursor = Stream;
+        if (Stream.SkipBlock() ||  // Skip with the main cursor.
+            // Read the abbrevs.
+            ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
+          Error("malformed block record in PCH file");
+          return Failure;
+        }
+        break;
+
+      case pch::PREPROCESSOR_BLOCK_ID:
+        MacroCursor = Stream;
+        if (PP)
+          PP->setExternalSource(this);
+
+        if (Stream.SkipBlock()) {
+          Error("malformed block record in PCH file");
+          return Failure;
+        }
+        break;
+
+      case pch::SOURCE_MANAGER_BLOCK_ID:
+        switch (ReadSourceManagerBlock()) {
+        case Success:
+          break;
+
+        case Failure:
+          Error("malformed source manager block in PCH file");
+          return Failure;
+
+        case IgnorePCH:
+          return IgnorePCH;
+        }
+        break;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read and process a record.
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
+                                                   &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+
+    case pch::TYPE_OFFSET:
+      if (!TypesLoaded.empty()) {
+        Error("duplicate TYPE_OFFSET record in PCH file");
+        return Failure;
+      }
+      TypeOffsets = (const uint32_t *)BlobStart;
+      TypesLoaded.resize(Record[0]);
+      break;
+
+    case pch::DECL_OFFSET:
+      if (!DeclsLoaded.empty()) {
+        Error("duplicate DECL_OFFSET record in PCH file");
+        return Failure;
+      }
+      DeclOffsets = (const uint32_t *)BlobStart;
+      DeclsLoaded.resize(Record[0]);
+      break;
+
+    case pch::LANGUAGE_OPTIONS:
+      if (ParseLanguageOptions(Record))
+        return IgnorePCH;
+      break;
+
+    case pch::METADATA: {
+      if (Record[0] != pch::VERSION_MAJOR) {
+        Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
+                                           : diag::warn_pch_version_too_new);
+        return IgnorePCH;
+      }
+
+      RelocatablePCH = Record[4];
+      if (Listener) {
+        std::string TargetTriple(BlobStart, BlobLen);
+        if (Listener->ReadTargetTriple(TargetTriple))
+          return IgnorePCH;
+      }
+      break;
+    }
+
+    case pch::IDENTIFIER_TABLE:
+      IdentifierTableData = BlobStart;
+      if (Record[0]) {
+        IdentifierLookupTable
+          = PCHIdentifierLookupTable::Create(
+                        (const unsigned char *)IdentifierTableData + Record[0],
+                        (const unsigned char *)IdentifierTableData,
+                        PCHIdentifierLookupTrait(*this));
+        if (PP)
+          PP->getIdentifierTable().setExternalIdentifierLookup(this);
+      }
+      break;
+
+    case pch::IDENTIFIER_OFFSET:
+      if (!IdentifiersLoaded.empty()) {
+        Error("duplicate IDENTIFIER_OFFSET record in PCH file");
+        return Failure;
+      }
+      IdentifierOffsets = (const uint32_t *)BlobStart;
+      IdentifiersLoaded.resize(Record[0]);
+      if (PP)
+        PP->getHeaderSearchInfo().SetExternalLookup(this);
+      break;
+
+    case pch::EXTERNAL_DEFINITIONS:
+      if (!ExternalDefinitions.empty()) {
+        Error("duplicate EXTERNAL_DEFINITIONS record in PCH file");
+        return Failure;
+      }
+      ExternalDefinitions.swap(Record);
+      break;
+
+    case pch::SPECIAL_TYPES:
+      SpecialTypes.swap(Record);
+      break;
+
+    case pch::STATISTICS:
+      TotalNumStatements = Record[0];
+      TotalNumMacros = Record[1];
+      TotalLexicalDeclContexts = Record[2];
+      TotalVisibleDeclContexts = Record[3];
+      break;
+
+    case pch::TENTATIVE_DEFINITIONS:
+      if (!TentativeDefinitions.empty()) {
+        Error("duplicate TENTATIVE_DEFINITIONS record in PCH file");
+        return Failure;
+      }
+      TentativeDefinitions.swap(Record);
+      break;
+
+    case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
+      if (!LocallyScopedExternalDecls.empty()) {
+        Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
+        return Failure;
+      }
+      LocallyScopedExternalDecls.swap(Record);
+      break;
+
+    case pch::SELECTOR_OFFSETS:
+      SelectorOffsets = (const uint32_t *)BlobStart;
+      TotalNumSelectors = Record[0];
+      SelectorsLoaded.resize(TotalNumSelectors);
+      break;
+
+    case pch::METHOD_POOL:
+      MethodPoolLookupTableData = (const unsigned char *)BlobStart;
+      if (Record[0])
+        MethodPoolLookupTable
+          = PCHMethodPoolLookupTable::Create(
+                        MethodPoolLookupTableData + Record[0],
+                        MethodPoolLookupTableData,
+                        PCHMethodPoolLookupTrait(*this));
+      TotalSelectorsInMethodPool = Record[1];
+      break;
+
+    case pch::PP_COUNTER_VALUE:
+      if (!Record.empty() && Listener)
+        Listener->ReadCounter(Record[0]);
+      break;
+
+    case pch::SOURCE_LOCATION_OFFSETS:
+      SLocOffsets = (const uint32_t *)BlobStart;
+      TotalNumSLocEntries = Record[0];
+      SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]);
+      break;
+
+    case pch::SOURCE_LOCATION_PRELOADS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I) {
+        PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
+        if (Result != Success)
+          return Result;
+      }
+      break;
+
+    case pch::STAT_CACHE: {
+      PCHStatCache *MyStatCache = 
+        new PCHStatCache((const unsigned char *)BlobStart + Record[0],
+                         (const unsigned char *)BlobStart,
+                         NumStatHits, NumStatMisses);
+      FileMgr.addStatCache(MyStatCache);
+      StatCache = MyStatCache;
+      break;
+    }
+        
+    case pch::EXT_VECTOR_DECLS:
+      if (!ExtVectorDecls.empty()) {
+        Error("duplicate EXT_VECTOR_DECLS record in PCH file");
+        return Failure;
+      }
+      ExtVectorDecls.swap(Record);
+      break;
+
+    case pch::ORIGINAL_FILE_NAME:
+      ActualOriginalFileName.assign(BlobStart, BlobLen);
+      OriginalFileName = ActualOriginalFileName;
+      MaybeAddSystemRootToFilename(OriginalFileName);
+      break;
+
+    case pch::COMMENT_RANGES:
+      Comments = (SourceRange *)BlobStart;
+      NumComments = BlobLen / sizeof(SourceRange);
+      break;
+        
+    case pch::VERSION_CONTROL_BRANCH_REVISION: {
+      llvm::StringRef CurBranch = getClangFullRepositoryVersion();
+      llvm::StringRef PCHBranch(BlobStart, BlobLen);
+      if (CurBranch != PCHBranch) {
+        Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
+        return IgnorePCH;
+      }
+      break;
+    }
+    }
+  }
+  Error("premature end of bitstream in PCH file");
+  return Failure;
+}
+
+PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
+  // Set the PCH file name.
+  this->FileName = FileName;
+
+  // Open the PCH file.
+  //
+  // FIXME: This shouldn't be here, we should just take a raw_ostream.
+  std::string ErrStr;
+  Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
+  if (!Buffer) {
+    Error(ErrStr.c_str());
+    return IgnorePCH;
+  }
+
+  // Initialize the stream
+  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+                  (const unsigned char *)Buffer->getBufferEnd());
+  Stream.init(StreamFile);
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'P' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'H') {
+    Diag(diag::err_not_a_pch_file) << FileName;
+    return Failure;
+  }
+
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code != llvm::bitc::ENTER_SUBBLOCK) {
+      Error("invalid record at top-level of PCH file");
+      return Failure;
+    }
+
+    unsigned BlockID = Stream.ReadSubBlockID();
+
+    // We only know the PCH subblock ID.
+    switch (BlockID) {
+    case llvm::bitc::BLOCKINFO_BLOCK_ID:
+      if (Stream.ReadBlockInfoBlock()) {
+        Error("malformed BlockInfoBlock in PCH file");
+        return Failure;
+      }
+      break;
+    case pch::PCH_BLOCK_ID:
+      switch (ReadPCHBlock()) {
+      case Success:
+        break;
+
+      case Failure:
+        return Failure;
+
+      case IgnorePCH:
+        // FIXME: We could consider reading through to the end of this
+        // PCH block, skipping subblocks, to see if there are other
+        // PCH blocks elsewhere.
+
+        // Clear out any preallocated source location entries, so that
+        // the source manager does not try to resolve them later.
+        SourceMgr.ClearPreallocatedSLocEntries();
+
+        // Remove the stat cache.
+        if (StatCache)
+          FileMgr.removeStatCache((PCHStatCache*)StatCache);
+
+        return IgnorePCH;
+      }
+      break;
+    default:
+      if (Stream.SkipBlock()) {
+        Error("malformed block record in PCH file");
+        return Failure;
+      }
+      break;
+    }
+  }
+
+  // Check the predefines buffer.
+  if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
+                            PCHPredefinesBufferID))
+    return IgnorePCH;
+
+  if (PP) {
+    // Initialization of keywords and pragmas occurs before the
+    // PCH file is read, so there may be some identifiers that were
+    // loaded into the IdentifierTable before we intercepted the
+    // creation of identifiers. Iterate through the list of known
+    // identifiers and determine whether we have to establish
+    // preprocessor definitions or top-level identifier declaration
+    // chains for those identifiers.
+    //
+    // We copy the IdentifierInfo pointers to a small vector first,
+    // since de-serializing declarations or macro definitions can add
+    // new entries into the identifier table, invalidating the
+    // iterators.
+    llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+    for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+                                IdEnd = PP->getIdentifierTable().end();
+         Id != IdEnd; ++Id)
+      Identifiers.push_back(Id->second);
+    PCHIdentifierLookupTable *IdTable
+      = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+    for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+      IdentifierInfo *II = Identifiers[I];
+      // Look in the on-disk hash table for an entry for
+      PCHIdentifierLookupTrait Info(*this, II);
+      std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
+      PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+      if (Pos == IdTable->end())
+        continue;
+
+      // Dereferencing the iterator has the effect of populating the
+      // IdentifierInfo node with the various declarations it needs.
+      (void)*Pos;
+    }
+  }
+
+  if (Context)
+    InitializeContext(*Context);
+
+  return Success;
+}
+
+void PCHReader::InitializeContext(ASTContext &Ctx) {
+  Context = &Ctx;
+  assert(Context && "Passed null context!");
+
+  assert(PP && "Forgot to set Preprocessor ?");
+  PP->getIdentifierTable().setExternalIdentifierLookup(this);
+  PP->getHeaderSearchInfo().SetExternalLookup(this);
+  PP->setExternalSource(this);
+  
+  // Load the translation unit declaration
+  ReadDeclRecord(DeclOffsets[0], 0);
+
+  // Load the special types.
+  Context->setBuiltinVaListType(
+    GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
+  if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+    Context->setObjCIdType(GetType(Id));
+  if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+    Context->setObjCSelType(GetType(Sel));
+  if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+    Context->setObjCProtoType(GetType(Proto));
+  if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+    Context->setObjCClassType(GetType(Class));
+
+  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+    Context->setCFConstantStringType(GetType(String));
+  if (unsigned FastEnum
+        = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+    Context->setObjCFastEnumerationStateType(GetType(FastEnum));
+  if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) {
+    QualType FileType = GetType(File);
+    assert(!FileType.isNull() && "FILE type is NULL");
+    if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
+      Context->setFILEDecl(Typedef->getDecl());
+    else {
+      const TagType *Tag = FileType->getAs<TagType>();
+      assert(Tag && "Invalid FILE type in PCH file");
+      Context->setFILEDecl(Tag->getDecl());
+    }
+  }
+  if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) {
+    QualType Jmp_bufType = GetType(Jmp_buf);
+    assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL");
+    if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
+      Context->setjmp_bufDecl(Typedef->getDecl());
+    else {
+      const TagType *Tag = Jmp_bufType->getAs<TagType>();
+      assert(Tag && "Invalid jmp_bug type in PCH file");
+      Context->setjmp_bufDecl(Tag->getDecl());
+    }
+  }
+  if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) {
+    QualType Sigjmp_bufType = GetType(Sigjmp_buf);
+    assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL");
+    if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
+      Context->setsigjmp_bufDecl(Typedef->getDecl());
+    else {
+      const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
+      assert(Tag && "Invalid sigjmp_buf type in PCH file");
+      Context->setsigjmp_bufDecl(Tag->getDecl());
+    }
+  }
+  if (unsigned ObjCIdRedef
+        = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION])
+    Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
+  if (unsigned ObjCClassRedef
+      = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
+    Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
+#if 0
+  // FIXME. Accommodate for this in several PCH/Index tests
+  if (unsigned ObjCSelRedef
+      = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION])
+    Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef);
+#endif
+  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
+    Context->setBlockDescriptorType(GetType(String));
+  if (unsigned String
+      = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
+    Context->setBlockDescriptorExtendedType(GetType(String));
+}
+
+/// \brief Retrieve the name of the original source file name
+/// directly from the PCH file, without actually loading the PCH
+/// file.
+std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
+                                             Diagnostic &Diags) {
+  // Open the PCH file.
+  std::string ErrStr;
+  llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+  Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
+  if (!Buffer) {
+    Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr;
+    return std::string();
+  }
+
+  // Initialize the stream
+  llvm::BitstreamReader StreamFile;
+  llvm::BitstreamCursor Stream;
+  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+                  (const unsigned char *)Buffer->getBufferEnd());
+  Stream.init(StreamFile);
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'P' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'H') {
+    Diags.Report(diag::err_fe_not_a_pch_file) << PCHFileName;
+    return std::string();
+  }
+
+  RecordData Record;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      unsigned BlockID = Stream.ReadSubBlockID();
+
+      // We only know the PCH subblock ID.
+      switch (BlockID) {
+      case pch::PCH_BLOCK_ID:
+        if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
+          Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
+          return std::string();
+        }
+        break;
+
+      default:
+        if (Stream.SkipBlock()) {
+          Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
+          return std::string();
+        }
+        break;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Diags.Report(diag::err_fe_pch_error_at_end_block) << PCHFileName;
+        return std::string();
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
+          == pch::ORIGINAL_FILE_NAME)
+      return std::string(BlobStart, BlobLen);
+  }
+
+  return std::string();
+}
+
+/// \brief Parse the record that corresponds to a LangOptions data
+/// structure.
+///
+/// This routine compares the language options used to generate the
+/// PCH file against the language options set for the current
+/// compilation. For each option, we classify differences between the
+/// two compiler states as either "benign" or "important". Benign
+/// differences don't matter, and we accept them without complaint
+/// (and without modifying the language options). Differences between
+/// the states for important options cause the PCH file to be
+/// unusable, so we emit a warning and return true to indicate that
+/// there was an error.
+///
+/// \returns true if the PCH file is unacceptable, false otherwise.
+bool PCHReader::ParseLanguageOptions(
+                             const llvm::SmallVectorImpl<uint64_t> &Record) {
+  if (Listener) {
+    LangOptions LangOpts;
+
+  #define PARSE_LANGOPT(Option)                  \
+      LangOpts.Option = Record[Idx];             \
+      ++Idx
+
+    unsigned Idx = 0;
+    PARSE_LANGOPT(Trigraphs);
+    PARSE_LANGOPT(BCPLComment);
+    PARSE_LANGOPT(DollarIdents);
+    PARSE_LANGOPT(AsmPreprocessor);
+    PARSE_LANGOPT(GNUMode);
+    PARSE_LANGOPT(ImplicitInt);
+    PARSE_LANGOPT(Digraphs);
+    PARSE_LANGOPT(HexFloats);
+    PARSE_LANGOPT(C99);
+    PARSE_LANGOPT(Microsoft);
+    PARSE_LANGOPT(CPlusPlus);
+    PARSE_LANGOPT(CPlusPlus0x);
+    PARSE_LANGOPT(CXXOperatorNames);
+    PARSE_LANGOPT(ObjC1);
+    PARSE_LANGOPT(ObjC2);
+    PARSE_LANGOPT(ObjCNonFragileABI);
+    PARSE_LANGOPT(ObjCNonFragileABI2);
+    PARSE_LANGOPT(PascalStrings);
+    PARSE_LANGOPT(WritableStrings);
+    PARSE_LANGOPT(LaxVectorConversions);
+    PARSE_LANGOPT(AltiVec);
+    PARSE_LANGOPT(Exceptions);
+    PARSE_LANGOPT(NeXTRuntime);
+    PARSE_LANGOPT(Freestanding);
+    PARSE_LANGOPT(NoBuiltin);
+    PARSE_LANGOPT(ThreadsafeStatics);
+    PARSE_LANGOPT(POSIXThreads);
+    PARSE_LANGOPT(Blocks);
+    PARSE_LANGOPT(EmitAllDecls);
+    PARSE_LANGOPT(MathErrno);
+    PARSE_LANGOPT(OverflowChecking);
+    PARSE_LANGOPT(HeinousExtensions);
+    PARSE_LANGOPT(Optimize);
+    PARSE_LANGOPT(OptimizeSize);
+    PARSE_LANGOPT(Static);
+    PARSE_LANGOPT(PICLevel);
+    PARSE_LANGOPT(GNUInline);
+    PARSE_LANGOPT(NoInline);
+    PARSE_LANGOPT(AccessControl);
+    PARSE_LANGOPT(CharIsSigned);
+    PARSE_LANGOPT(ShortWChar);
+    LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
+    ++Idx;
+    LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
+    ++Idx;
+    LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
+                                   Record[Idx]);
+    ++Idx;
+    PARSE_LANGOPT(InstantiationDepth);
+    PARSE_LANGOPT(OpenCL);
+    PARSE_LANGOPT(CatchUndefined);
+    // FIXME: Missing ElideConstructors?!
+  #undef PARSE_LANGOPT
+
+    return Listener->ReadLanguageOptions(LangOpts);
+  }
+
+  return false;
+}
+
+void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
+  Comments.resize(NumComments);
+  std::copy(this->Comments, this->Comments + NumComments,
+            Comments.begin());
+}
+
+/// \brief Read and return the type at the given offset.
+///
+/// This routine actually reads the record corresponding to the type
+/// at the given offset in the bitstream. It is a helper routine for
+/// GetType, which deals with reading type IDs.
+QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this type.
+  SavedStreamPosition SavedPosition(DeclsCursor);
+
+  // Note that we are loading a type record.
+  LoadingTypeOrDecl Loading(*this);
+
+  DeclsCursor.JumpToBit(Offset);
+  RecordData Record;
+  unsigned Code = DeclsCursor.ReadCode();
+  switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
+  case pch::TYPE_EXT_QUAL: {
+    assert(Record.size() == 2 &&
+           "Incorrect encoding of extended qualifier type");
+    QualType Base = GetType(Record[0]);
+    Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
+    return Context->getQualifiedType(Base, Quals);
+  }
+
+  case pch::TYPE_COMPLEX: {
+    assert(Record.size() == 1 && "Incorrect encoding of complex type");
+    QualType ElemType = GetType(Record[0]);
+    return Context->getComplexType(ElemType);
+  }
+
+  case pch::TYPE_POINTER: {
+    assert(Record.size() == 1 && "Incorrect encoding of pointer type");
+    QualType PointeeType = GetType(Record[0]);
+    return Context->getPointerType(PointeeType);
+  }
+
+  case pch::TYPE_BLOCK_POINTER: {
+    assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
+    QualType PointeeType = GetType(Record[0]);
+    return Context->getBlockPointerType(PointeeType);
+  }
+
+  case pch::TYPE_LVALUE_REFERENCE: {
+    assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
+    QualType PointeeType = GetType(Record[0]);
+    return Context->getLValueReferenceType(PointeeType);
+  }
+
+  case pch::TYPE_RVALUE_REFERENCE: {
+    assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
+    QualType PointeeType = GetType(Record[0]);
+    return Context->getRValueReferenceType(PointeeType);
+  }
+
+  case pch::TYPE_MEMBER_POINTER: {
+    assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
+    QualType PointeeType = GetType(Record[0]);
+    QualType ClassType = GetType(Record[1]);
+    return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
+  }
+
+  case pch::TYPE_CONSTANT_ARRAY: {
+    QualType ElementType = GetType(Record[0]);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    unsigned Idx = 3;
+    llvm::APInt Size = ReadAPInt(Record, Idx);
+    return Context->getConstantArrayType(ElementType, Size,
+                                         ASM, IndexTypeQuals);
+  }
+
+  case pch::TYPE_INCOMPLETE_ARRAY: {
+    QualType ElementType = GetType(Record[0]);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
+  }
+
+  case pch::TYPE_VARIABLE_ARRAY: {
+    QualType ElementType = GetType(Record[0]);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
+    SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
+    return Context->getVariableArrayType(ElementType, ReadTypeExpr(),
+                                         ASM, IndexTypeQuals,
+                                         SourceRange(LBLoc, RBLoc));
+  }
+
+  case pch::TYPE_VECTOR: {
+    if (Record.size() != 4) {
+      Error("incorrect encoding of vector type in PCH file");
+      return QualType();
+    }
+
+    QualType ElementType = GetType(Record[0]);
+    unsigned NumElements = Record[1];
+    bool AltiVec = Record[2];
+    bool Pixel = Record[3];
+    return Context->getVectorType(ElementType, NumElements, AltiVec, Pixel);
+  }
+
+  case pch::TYPE_EXT_VECTOR: {
+    if (Record.size() != 4) {
+      Error("incorrect encoding of extended vector type in PCH file");
+      return QualType();
+    }
+
+    QualType ElementType = GetType(Record[0]);
+    unsigned NumElements = Record[1];
+    return Context->getExtVectorType(ElementType, NumElements);
+  }
+
+  case pch::TYPE_FUNCTION_NO_PROTO: {
+    if (Record.size() != 3) {
+      Error("incorrect encoding of no-proto function type");
+      return QualType();
+    }
+    QualType ResultType = GetType(Record[0]);
+    return Context->getFunctionNoProtoType(ResultType, Record[1],
+                                           (CallingConv)Record[2]);
+  }
+
+  case pch::TYPE_FUNCTION_PROTO: {
+    QualType ResultType = GetType(Record[0]);
+    bool NoReturn = Record[1];
+    CallingConv CallConv = (CallingConv)Record[2];
+    unsigned Idx = 3;
+    unsigned NumParams = Record[Idx++];
+    llvm::SmallVector<QualType, 16> ParamTypes;
+    for (unsigned I = 0; I != NumParams; ++I)
+      ParamTypes.push_back(GetType(Record[Idx++]));
+    bool isVariadic = Record[Idx++];
+    unsigned Quals = Record[Idx++];
+    bool hasExceptionSpec = Record[Idx++];
+    bool hasAnyExceptionSpec = Record[Idx++];
+    unsigned NumExceptions = Record[Idx++];
+    llvm::SmallVector<QualType, 2> Exceptions;
+    for (unsigned I = 0; I != NumExceptions; ++I)
+      Exceptions.push_back(GetType(Record[Idx++]));
+    return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
+                                    isVariadic, Quals, hasExceptionSpec,
+                                    hasAnyExceptionSpec, NumExceptions,
+                                    Exceptions.data(), NoReturn, CallConv);
+  }
+
+  case pch::TYPE_UNRESOLVED_USING:
+    return Context->getTypeDeclType(
+             cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
+
+  case pch::TYPE_TYPEDEF:
+    assert(Record.size() == 1 && "incorrect encoding of typedef type");
+    return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
+
+  case pch::TYPE_TYPEOF_EXPR:
+    return Context->getTypeOfExprType(ReadTypeExpr());
+
+  case pch::TYPE_TYPEOF: {
+    if (Record.size() != 1) {
+      Error("incorrect encoding of typeof(type) in PCH file");
+      return QualType();
+    }
+    QualType UnderlyingType = GetType(Record[0]);
+    return Context->getTypeOfType(UnderlyingType);
+  }
+
+  case pch::TYPE_DECLTYPE:
+    return Context->getDecltypeType(ReadTypeExpr());
+
+  case pch::TYPE_RECORD:
+    assert(Record.size() == 1 && "incorrect encoding of record type");
+    return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
+
+  case pch::TYPE_ENUM:
+    assert(Record.size() == 1 && "incorrect encoding of enum type");
+    return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
+
+  case pch::TYPE_ELABORATED: {
+    assert(Record.size() == 2 && "incorrect encoding of elaborated type");
+    unsigned Tag = Record[1];
+    return Context->getElaboratedType(GetType(Record[0]),
+                                      (ElaboratedType::TagKind) Tag);
+  }
+
+  case pch::TYPE_OBJC_INTERFACE: {
+    unsigned Idx = 0;
+    ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
+    unsigned NumProtos = Record[Idx++];
+    llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
+    for (unsigned I = 0; I != NumProtos; ++I)
+      Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
+    return Context->getObjCInterfaceType(ItfD, Protos.data(), NumProtos);
+  }
+
+  case pch::TYPE_OBJC_OBJECT_POINTER: {
+    unsigned Idx = 0;
+    QualType OIT = GetType(Record[Idx++]);
+    unsigned NumProtos = Record[Idx++];
+    llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
+    for (unsigned I = 0; I != NumProtos; ++I)
+      Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
+    return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
+  }
+
+  case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
+    unsigned Idx = 0;
+    QualType Parm = GetType(Record[Idx++]);
+    QualType Replacement = GetType(Record[Idx++]);
+    return
+      Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
+                                            Replacement);
+  }
+  }
+  // Suppress a GCC warning
+  return QualType();
+}
+
+namespace {
+
+class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+  PCHReader &Reader;
+  const PCHReader::RecordData &Record;
+  unsigned &Idx;
+
+public:
+  TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
+                unsigned &Idx)
+    : Reader(Reader), Record(Record), Idx(Idx) { }
+
+  // We want compile-time assurance that we've enumerated all of
+  // these, so unfortunately we have to declare them first, then
+  // define them out-of-line.
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+  void VisitFunctionTypeLoc(FunctionTypeLoc);
+  void VisitArrayTypeLoc(ArrayTypeLoc);
+};
+
+}
+
+void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+  // nothing to do
+}
+void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+  TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  if (TL.needsExtraLocalData()) {
+    TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
+    TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
+    TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
+    TL.setModeAttr(Record[Idx++]);
+  }
+}
+void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
+  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+  TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+  TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+  TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+  TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  if (Record[Idx++])
+    TL.setSizeExpr(Reader.ReadDeclExpr());
+  else
+    TL.setSizeExpr(0);
+}
+void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedArrayTypeLoc(
+                                            DependentSizedArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
+                                        DependentSizedExtVectorTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+    TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+  }
+}
+void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+  VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+  VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+  TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+  TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx));
+}
+void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
+                                            SubstTemplateTypeParmTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTemplateSpecializationTypeLoc(
+                                           TemplateSpecializationTypeLoc TL) {
+  TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    TL.setArgLocInfo(i,
+        Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
+                                          Record, Idx));
+}
+void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+    TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setHasBaseTypeAsWritten(Record[Idx++]);
+  TL.setHasProtocolsAsWritten(Record[Idx++]);
+  if (TL.hasProtocolsAsWritten())
+    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+      TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
+TypeSourceInfo *PCHReader::GetTypeSourceInfo(const RecordData &Record,
+                                             unsigned &Idx) {
+  QualType InfoTy = GetType(Record[Idx++]);
+  if (InfoTy.isNull())
+    return 0;
+
+  TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy);
+  TypeLocReader TLR(*this, Record, Idx);
+  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+    TLR.Visit(TL);
+  return TInfo;
+}
+
+QualType PCHReader::GetType(pch::TypeID ID) {
+  unsigned FastQuals = ID & Qualifiers::FastMask;
+  unsigned Index = ID >> Qualifiers::FastWidth;
+
+  if (Index < pch::NUM_PREDEF_TYPE_IDS) {
+    QualType T;
+    switch ((pch::PredefinedTypeIDs)Index) {
+    case pch::PREDEF_TYPE_NULL_ID: return QualType();
+    case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
+    case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
+
+    case pch::PREDEF_TYPE_CHAR_U_ID:
+    case pch::PREDEF_TYPE_CHAR_S_ID:
+      // FIXME: Check that the signedness of CharTy is correct!
+      T = Context->CharTy;
+      break;
+
+    case pch::PREDEF_TYPE_UCHAR_ID:      T = Context->UnsignedCharTy;     break;
+    case pch::PREDEF_TYPE_USHORT_ID:     T = Context->UnsignedShortTy;    break;
+    case pch::PREDEF_TYPE_UINT_ID:       T = Context->UnsignedIntTy;      break;
+    case pch::PREDEF_TYPE_ULONG_ID:      T = Context->UnsignedLongTy;     break;
+    case pch::PREDEF_TYPE_ULONGLONG_ID:  T = Context->UnsignedLongLongTy; break;
+    case pch::PREDEF_TYPE_UINT128_ID:    T = Context->UnsignedInt128Ty;   break;
+    case pch::PREDEF_TYPE_SCHAR_ID:      T = Context->SignedCharTy;       break;
+    case pch::PREDEF_TYPE_WCHAR_ID:      T = Context->WCharTy;            break;
+    case pch::PREDEF_TYPE_SHORT_ID:      T = Context->ShortTy;            break;
+    case pch::PREDEF_TYPE_INT_ID:        T = Context->IntTy;              break;
+    case pch::PREDEF_TYPE_LONG_ID:       T = Context->LongTy;             break;
+    case pch::PREDEF_TYPE_LONGLONG_ID:   T = Context->LongLongTy;         break;
+    case pch::PREDEF_TYPE_INT128_ID:     T = Context->Int128Ty;           break;
+    case pch::PREDEF_TYPE_FLOAT_ID:      T = Context->FloatTy;            break;
+    case pch::PREDEF_TYPE_DOUBLE_ID:     T = Context->DoubleTy;           break;
+    case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy;       break;
+    case pch::PREDEF_TYPE_OVERLOAD_ID:   T = Context->OverloadTy;         break;
+    case pch::PREDEF_TYPE_DEPENDENT_ID:  T = Context->DependentTy;        break;
+    case pch::PREDEF_TYPE_NULLPTR_ID:    T = Context->NullPtrTy;          break;
+    case pch::PREDEF_TYPE_CHAR16_ID:     T = Context->Char16Ty;           break;
+    case pch::PREDEF_TYPE_CHAR32_ID:     T = Context->Char32Ty;           break;
+    case pch::PREDEF_TYPE_OBJC_ID:       T = Context->ObjCBuiltinIdTy;    break;
+    case pch::PREDEF_TYPE_OBJC_CLASS:    T = Context->ObjCBuiltinClassTy; break;
+    case pch::PREDEF_TYPE_OBJC_SEL:      T = Context->ObjCBuiltinSelTy;   break;
+    }
+
+    assert(!T.isNull() && "Unknown predefined type");
+    return T.withFastQualifiers(FastQuals);
+  }
+
+  Index -= pch::NUM_PREDEF_TYPE_IDS;
+  //assert(Index < TypesLoaded.size() && "Type index out-of-range");
+  if (TypesLoaded[Index].isNull())
+    TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
+
+  return TypesLoaded[Index].withFastQualifiers(FastQuals);
+}
+
+TemplateArgumentLocInfo
+PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+                                      const RecordData &Record,
+                                      unsigned &Index) {
+  switch (Kind) {
+  case TemplateArgument::Expression:
+    return ReadDeclExpr();
+  case TemplateArgument::Type:
+    return GetTypeSourceInfo(Record, Index);
+  case TemplateArgument::Template: {
+    SourceLocation 
+      QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
+      QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
+      TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
+    return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
+                                   TemplateNameLoc);
+  }
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Pack:
+    return TemplateArgumentLocInfo();
+  }
+  llvm_unreachable("unexpected template argument loc");
+  return TemplateArgumentLocInfo();
+}
+
+Decl *PCHReader::GetDecl(pch::DeclID ID) {
+  if (ID == 0)
+    return 0;
+
+  if (ID > DeclsLoaded.size()) {
+    Error("declaration ID out-of-range for PCH file");
+    return 0;
+  }
+
+  unsigned Index = ID - 1;
+  if (!DeclsLoaded[Index])
+    ReadDeclRecord(DeclOffsets[Index], Index);
+
+  return DeclsLoaded[Index];
+}
+
+/// \brief Resolve the offset of a statement into a statement.
+///
+/// This operation will read a new statement from the external
+/// source each time it is called, and is meant to be used via a
+/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
+Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
+  // Since we know tha this statement is part of a decl, make sure to use the
+  // decl cursor to read it.
+  DeclsCursor.JumpToBit(Offset);
+  return ReadStmt(DeclsCursor);
+}
+
+bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
+                                  llvm::SmallVectorImpl<pch::DeclID> &Decls) {
+  assert(DC->hasExternalLexicalStorage() &&
+         "DeclContext has no lexical decls in storage");
+  uint64_t Offset = DeclContextOffsets[DC].first;
+  assert(Offset && "DeclContext has no lexical decls in storage");
+
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this context.
+  SavedStreamPosition SavedPosition(DeclsCursor);
+
+  // Load the record containing all of the declarations lexically in
+  // this context.
+  DeclsCursor.JumpToBit(Offset);
+  RecordData Record;
+  unsigned Code = DeclsCursor.ReadCode();
+  unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
+  (void)RecCode;
+  assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
+
+  // Load all of the declaration IDs
+  Decls.clear();
+  Decls.insert(Decls.end(), Record.begin(), Record.end());
+  ++NumLexicalDeclContextsRead;
+  return false;
+}
+
+bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
+                           llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
+  assert(DC->hasExternalVisibleStorage() &&
+         "DeclContext has no visible decls in storage");
+  uint64_t Offset = DeclContextOffsets[DC].second;
+  assert(Offset && "DeclContext has no visible decls in storage");
+
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this context.
+  SavedStreamPosition SavedPosition(DeclsCursor);
+
+  // Load the record containing all of the declarations visible in
+  // this context.
+  DeclsCursor.JumpToBit(Offset);
+  RecordData Record;
+  unsigned Code = DeclsCursor.ReadCode();
+  unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
+  (void)RecCode;
+  assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
+  if (Record.size() == 0)
+    return false;
+
+  Decls.clear();
+
+  unsigned Idx = 0;
+  while (Idx < Record.size()) {
+    Decls.push_back(VisibleDeclaration());
+    Decls.back().Name = ReadDeclarationName(Record, Idx);
+
+    unsigned Size = Record[Idx++];
+    llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
+    LoadedDecls.reserve(Size);
+    for (unsigned I = 0; I < Size; ++I)
+      LoadedDecls.push_back(Record[Idx++]);
+  }
+
+  ++NumVisibleDeclContextsRead;
+  return false;
+}
+
+void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
+  this->Consumer = Consumer;
+
+  if (!Consumer)
+    return;
+
+  for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
+    // Force deserialization of this decl, which will cause it to be passed to
+    // the consumer (or queued).
+    GetDecl(ExternalDefinitions[I]);
+  }
+
+  for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
+    DeclGroupRef DG(InterestingDecls[I]);
+    Consumer->HandleTopLevelDecl(DG);
+  }
+}
+
+void PCHReader::PrintStats() {
+  std::fprintf(stderr, "*** PCH Statistics:\n");
+
+  unsigned NumTypesLoaded
+    = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
+                                      QualType());
+  unsigned NumDeclsLoaded
+    = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
+                                      (Decl *)0);
+  unsigned NumIdentifiersLoaded
+    = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
+                                            IdentifiersLoaded.end(),
+                                            (IdentifierInfo *)0);
+  unsigned NumSelectorsLoaded
+    = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
+                                          SelectorsLoaded.end(),
+                                          Selector());
+
+  std::fprintf(stderr, "  %u stat cache hits\n", NumStatHits);
+  std::fprintf(stderr, "  %u stat cache misses\n", NumStatMisses);
+  if (TotalNumSLocEntries)
+    std::fprintf(stderr, "  %u/%u source location entries read (%f%%)\n",
+                 NumSLocEntriesRead, TotalNumSLocEntries,
+                 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
+  if (!TypesLoaded.empty())
+    std::fprintf(stderr, "  %u/%u types read (%f%%)\n",
+                 NumTypesLoaded, (unsigned)TypesLoaded.size(),
+                 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
+  if (!DeclsLoaded.empty())
+    std::fprintf(stderr, "  %u/%u declarations read (%f%%)\n",
+                 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
+                 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
+  if (!IdentifiersLoaded.empty())
+    std::fprintf(stderr, "  %u/%u identifiers read (%f%%)\n",
+                 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
+                 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
+  if (TotalNumSelectors)
+    std::fprintf(stderr, "  %u/%u selectors read (%f%%)\n",
+                 NumSelectorsLoaded, TotalNumSelectors,
+                 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
+  if (TotalNumStatements)
+    std::fprintf(stderr, "  %u/%u statements read (%f%%)\n",
+                 NumStatementsRead, TotalNumStatements,
+                 ((float)NumStatementsRead/TotalNumStatements * 100));
+  if (TotalNumMacros)
+    std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
+                 NumMacrosRead, TotalNumMacros,
+                 ((float)NumMacrosRead/TotalNumMacros * 100));
+  if (TotalLexicalDeclContexts)
+    std::fprintf(stderr, "  %u/%u lexical declcontexts read (%f%%)\n",
+                 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
+                 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
+                  * 100));
+  if (TotalVisibleDeclContexts)
+    std::fprintf(stderr, "  %u/%u visible declcontexts read (%f%%)\n",
+                 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
+                 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
+                  * 100));
+  if (TotalSelectorsInMethodPool) {
+    std::fprintf(stderr, "  %u/%u method pool entries read (%f%%)\n",
+                 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
+                 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
+                  * 100));
+    std::fprintf(stderr, "  %u method pool misses\n", NumMethodPoolMisses);
+  }
+  std::fprintf(stderr, "\n");
+}
+
+void PCHReader::InitializeSema(Sema &S) {
+  SemaObj = &S;
+  S.ExternalSource = this;
+
+  // Makes sure any declarations that were deserialized "too early"
+  // still get added to the identifier's declaration chains.
+  for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
+    SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
+    SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
+  }
+  PreloadedDecls.clear();
+
+  // If there were any tentative definitions, deserialize them and add
+  // them to Sema's list of tentative definitions.
+  for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
+    VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
+    SemaObj->TentativeDefinitions.push_back(Var);
+  }
+
+  // If there were any locally-scoped external declarations,
+  // deserialize them and add them to Sema's table of locally-scoped
+  // external declarations.
+  for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
+    NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
+    SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
+  }
+
+  // If there were any ext_vector type declarations, deserialize them
+  // and add them to Sema's vector of such declarations.
+  for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
+    SemaObj->ExtVectorDecls.push_back(
+                               cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
+}
+
+IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
+  // Try to find this name within our on-disk hash table
+  PCHIdentifierLookupTable *IdTable
+    = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+  std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
+  PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
+  if (Pos == IdTable->end())
+    return 0;
+
+  // Dereferencing the iterator has the effect of building the
+  // IdentifierInfo node and populating it with the various
+  // declarations it needs.
+  return *Pos;
+}
+
+std::pair<ObjCMethodList, ObjCMethodList>
+PCHReader::ReadMethodPool(Selector Sel) {
+  if (!MethodPoolLookupTable)
+    return std::pair<ObjCMethodList, ObjCMethodList>();
+
+  // Try to find this selector within our on-disk hash table.
+  PCHMethodPoolLookupTable *PoolTable
+    = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
+  PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
+  if (Pos == PoolTable->end()) {
+    ++NumMethodPoolMisses;
+    return std::pair<ObjCMethodList, ObjCMethodList>();;
+  }
+
+  ++NumMethodPoolSelectorsRead;
+  return *Pos;
+}
+
+void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
+  assert(ID && "Non-zero identifier ID required");
+  assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
+  IdentifiersLoaded[ID - 1] = II;
+}
+
+/// \brief Set the globally-visible declarations associated with the given
+/// identifier.
+///
+/// If the PCH reader is currently in a state where the given declaration IDs
+/// cannot safely be resolved, they are queued until it is safe to resolve
+/// them.
+///
+/// \param II an IdentifierInfo that refers to one or more globally-visible
+/// declarations.
+///
+/// \param DeclIDs the set of declaration IDs with the name @p II that are
+/// visible at global scope.
+///
+/// \param Nonrecursive should be true to indicate that the caller knows that
+/// this call is non-recursive, and therefore the globally-visible declarations
+/// will not be placed onto the pending queue.
+void
+PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
+                              const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
+                                   bool Nonrecursive) {
+  if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) {
+    PendingIdentifierInfos.push_back(PendingIdentifierInfo());
+    PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
+    PII.II = II;
+    for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I)
+      PII.DeclIDs.push_back(DeclIDs[I]);
+    return;
+  }
+
+  for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
+    NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
+    if (SemaObj) {
+      // Introduce this declaration into the translation-unit scope
+      // and add it to the declaration chain for this identifier, so
+      // that (unqualified) name lookup will find it.
+      SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
+      SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
+    } else {
+      // Queue this declaration so that it will be added to the
+      // translation unit scope and identifier's declaration chain
+      // once a Sema object is known.
+      PreloadedDecls.push_back(D);
+    }
+  }
+}
+
+IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
+  if (ID == 0)
+    return 0;
+
+  if (!IdentifierTableData || IdentifiersLoaded.empty()) {
+    Error("no identifier table in PCH file");
+    return 0;
+  }
+
+  assert(PP && "Forgot to set Preprocessor ?");
+  if (!IdentifiersLoaded[ID - 1]) {
+    uint32_t Offset = IdentifierOffsets[ID - 1];
+    const char *Str = IdentifierTableData + Offset;
+
+    // All of the strings in the PCH file are preceded by a 16-bit
+    // length. Extract that 16-bit length to avoid having to execute
+    // strlen().
+    // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
+    //  unsigned integers.  This is important to avoid integer overflow when
+    //  we cast them to 'unsigned'.
+    const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
+    unsigned StrLen = (((unsigned) StrLenPtr[0])
+                       | (((unsigned) StrLenPtr[1]) << 8)) - 1;
+    IdentifiersLoaded[ID - 1]
+      = &PP->getIdentifierTable().get(Str, Str + StrLen);
+  }
+
+  return IdentifiersLoaded[ID - 1];
+}
+
+void PCHReader::ReadSLocEntry(unsigned ID) {
+  ReadSLocEntryRecord(ID);
+}
+
+Selector PCHReader::DecodeSelector(unsigned ID) {
+  if (ID == 0)
+    return Selector();
+
+  if (!MethodPoolLookupTableData)
+    return Selector();
+
+  if (ID > TotalNumSelectors) {
+    Error("selector ID out of range in PCH file");
+    return Selector();
+  }
+
+  unsigned Index = ID - 1;
+  if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
+    // Load this selector from the selector table.
+    // FIXME: endianness portability issues with SelectorOffsets table
+    PCHMethodPoolLookupTrait Trait(*this);
+    SelectorsLoaded[Index]
+      = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
+  }
+
+  return SelectorsLoaded[Index];
+}
+
+DeclarationName
+PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
+  DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
+  switch (Kind) {
+  case DeclarationName::Identifier:
+    return DeclarationName(GetIdentifierInfo(Record, Idx));
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    return DeclarationName(GetSelector(Record, Idx));
+
+  case DeclarationName::CXXConstructorName:
+    return Context->DeclarationNames.getCXXConstructorName(
+                          Context->getCanonicalType(GetType(Record[Idx++])));
+
+  case DeclarationName::CXXDestructorName:
+    return Context->DeclarationNames.getCXXDestructorName(
+                          Context->getCanonicalType(GetType(Record[Idx++])));
+
+  case DeclarationName::CXXConversionFunctionName:
+    return Context->DeclarationNames.getCXXConversionFunctionName(
+                          Context->getCanonicalType(GetType(Record[Idx++])));
+
+  case DeclarationName::CXXOperatorName:
+    return Context->DeclarationNames.getCXXOperatorName(
+                                       (OverloadedOperatorKind)Record[Idx++]);
+
+  case DeclarationName::CXXLiteralOperatorName:
+    return Context->DeclarationNames.getCXXLiteralOperatorName(
+                                       GetIdentifierInfo(Record, Idx));
+
+  case DeclarationName::CXXUsingDirective:
+    return DeclarationName::getUsingDirectiveName();
+  }
+
+  // Required to silence GCC warning
+  return DeclarationName();
+}
+
+/// \brief Read an integral value
+llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
+  unsigned BitWidth = Record[Idx++];
+  unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+  llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
+  Idx += NumWords;
+  return Result;
+}
+
+/// \brief Read a signed integral value
+llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
+  bool isUnsigned = Record[Idx++];
+  return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
+}
+
+/// \brief Read a floating-point value
+llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
+  return llvm::APFloat(ReadAPInt(Record, Idx));
+}
+
+// \brief Read a string
+std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
+  unsigned Len = Record[Idx++];
+  std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
+  Idx += Len;
+  return Result;
+}
+
+DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
+  return Diag(SourceLocation(), DiagID);
+}
+
+DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
+  return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
+}
+
+/// \brief Retrieve the identifier table associated with the
+/// preprocessor.
+IdentifierTable &PCHReader::getIdentifierTable() {
+  assert(PP && "Forgot to set Preprocessor ?");
+  return PP->getIdentifierTable();
+}
+
+/// \brief Record that the given ID maps to the given switch-case
+/// statement.
+void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+  assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
+  SwitchCaseStmts[ID] = SC;
+}
+
+/// \brief Retrieve the switch-case statement with the given ID.
+SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
+  assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
+  return SwitchCaseStmts[ID];
+}
+
+/// \brief Record that the given label statement has been
+/// deserialized and has the given ID.
+void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
+  assert(LabelStmts.find(ID) == LabelStmts.end() &&
+         "Deserialized label twice");
+  LabelStmts[ID] = S;
+
+  // If we've already seen any goto statements that point to this
+  // label, resolve them now.
+  typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
+  std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
+  for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
+    Goto->second->setLabel(S);
+  UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
+
+  // If we've already seen any address-label statements that point to
+  // this label, resolve them now.
+  typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
+  std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
+    = UnresolvedAddrLabelExprs.equal_range(ID);
+  for (AddrLabelIter AddrLabel = AddrLabels.first;
+       AddrLabel != AddrLabels.second; ++AddrLabel)
+    AddrLabel->second->setLabel(S);
+  UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
+}
+
+/// \brief Set the label of the given statement to the label
+/// identified by ID.
+///
+/// Depending on the order in which the label and other statements
+/// referencing that label occur, this operation may complete
+/// immediately (updating the statement) or it may queue the
+/// statement to be back-patched later.
+void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
+  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
+  if (Label != LabelStmts.end()) {
+    // We've already seen this label, so set the label of the goto and
+    // we're done.
+    S->setLabel(Label->second);
+  } else {
+    // We haven't seen this label yet, so add this goto to the set of
+    // unresolved goto statements.
+    UnresolvedGotoStmts.insert(std::make_pair(ID, S));
+  }
+}
+
+/// \brief Set the label of the given expression to the label
+/// identified by ID.
+///
+/// Depending on the order in which the label and other statements
+/// referencing that label occur, this operation may complete
+/// immediately (updating the statement) or it may queue the
+/// statement to be back-patched later.
+void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
+  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
+  if (Label != LabelStmts.end()) {
+    // We've already seen this label, so set the label of the
+    // label-address expression and we're done.
+    S->setLabel(Label->second);
+  } else {
+    // We haven't seen this label yet, so add this label-address
+    // expression to the set of unresolved label-address expressions.
+    UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
+  }
+}
+
+
+PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader)
+  : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) {
+  Reader.CurrentlyLoadingTypeOrDecl = this;
+}
+
+PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() {
+  if (!Parent) {
+    // If any identifiers with corresponding top-level declarations have
+    // been loaded, load those declarations now.
+    while (!Reader.PendingIdentifierInfos.empty()) {
+      Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II,
+                                 Reader.PendingIdentifierInfos.front().DeclIDs,
+                                     true);
+      Reader.PendingIdentifierInfos.pop_front();
+    }
+  }
+
+  Reader.CurrentlyLoadingTypeOrDecl = Parent;
+}
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
new file mode 100644
index 0000000..56cdfc6
--- /dev/null
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -0,0 +1,772 @@
+//===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PCHReader::ReadDeclRecord method, which is the
+// entrypoint for loading a decl.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHReader.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
+using namespace clang;
+
+
+//===----------------------------------------------------------------------===//
+// Declaration deserialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> {
+    PCHReader &Reader;
+    const PCHReader::RecordData &Record;
+    unsigned &Idx;
+
+  public:
+    PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record,
+                  unsigned &Idx)
+      : Reader(Reader), Record(Record), Idx(Idx) { }
+
+    void VisitDecl(Decl *D);
+    void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
+    void VisitNamedDecl(NamedDecl *ND);
+    void VisitTypeDecl(TypeDecl *TD);
+    void VisitTypedefDecl(TypedefDecl *TD);
+    void VisitTagDecl(TagDecl *TD);
+    void VisitEnumDecl(EnumDecl *ED);
+    void VisitRecordDecl(RecordDecl *RD);
+    void VisitValueDecl(ValueDecl *VD);
+    void VisitEnumConstantDecl(EnumConstantDecl *ECD);
+    void VisitDeclaratorDecl(DeclaratorDecl *DD);
+    void VisitFunctionDecl(FunctionDecl *FD);
+    void VisitFieldDecl(FieldDecl *FD);
+    void VisitVarDecl(VarDecl *VD);
+    void VisitImplicitParamDecl(ImplicitParamDecl *PD);
+    void VisitParmVarDecl(ParmVarDecl *PD);
+    void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
+    void VisitBlockDecl(BlockDecl *BD);
+    std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+    void VisitObjCMethodDecl(ObjCMethodDecl *D);
+    void VisitObjCContainerDecl(ObjCContainerDecl *D);
+    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+    void VisitObjCIvarDecl(ObjCIvarDecl *D);
+    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+    void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
+    void VisitObjCClassDecl(ObjCClassDecl *D);
+    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+    void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
+    void VisitObjCImplDecl(ObjCImplDecl *D);
+    void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+    void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+    void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
+    void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+    void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+  };
+}
+
+void PCHDeclReader::VisitDecl(Decl *D) {
+  D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
+  D->setLexicalDeclContext(
+                     cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
+  D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  D->setInvalidDecl(Record[Idx++]);
+  if (Record[Idx++])
+    D->addAttr(Reader.ReadAttributes());
+  D->setImplicit(Record[Idx++]);
+  D->setUsed(Record[Idx++]);
+  D->setAccess((AccessSpecifier)Record[Idx++]);
+  D->setPCHLevel(Record[Idx++] + 1);
+}
+
+void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
+  VisitDecl(TU);
+}
+
+void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
+  VisitDecl(ND);
+  ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
+}
+
+void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
+  VisitNamedDecl(TD);
+  TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
+}
+
+void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
+  // Note that we cannot use VisitTypeDecl here, because we need to
+  // set the underlying type of the typedef *before* we try to read
+  // the type associated with the TypedefDecl.
+  VisitNamedDecl(TD);
+  uint64_t TypeData = Record[Idx++];
+  TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+  TD->setTypeForDecl(Reader.GetType(TypeData).getTypePtr());
+}
+
+void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
+  VisitTypeDecl(TD);
+  TD->setPreviousDeclaration(
+                        cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++])));
+  TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
+  TD->setDefinition(Record[Idx++]);
+  TD->setDefinedInDeclarator(Record[Idx++]);
+  TD->setTypedefForAnonDecl(
+                    cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
+  TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
+void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
+  VisitTagDecl(ED);
+  ED->setIntegerType(Reader.GetType(Record[Idx++]));
+  ED->setPromotionType(Reader.GetType(Record[Idx++]));
+  // FIXME: C++ InstantiatedFrom
+}
+
+void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
+  VisitTagDecl(RD);
+  RD->setHasFlexibleArrayMember(Record[Idx++]);
+  RD->setAnonymousStructOrUnion(Record[Idx++]);
+  RD->setHasObjectMember(Record[Idx++]);
+}
+
+void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
+  VisitNamedDecl(VD);
+  VD->setType(Reader.GetType(Record[Idx++]));
+}
+
+void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
+  VisitValueDecl(ECD);
+  if (Record[Idx++])
+    ECD->setInitExpr(Reader.ReadDeclExpr());
+  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
+}
+
+void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+  VisitValueDecl(DD);
+  TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx);
+  if (TInfo)
+    DD->setTypeSourceInfo(TInfo);
+}
+
+void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
+  VisitDeclaratorDecl(FD);
+  if (Record[Idx++])
+    FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo());
+  FD->setPreviousDeclaration(
+                   cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
+  FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
+  FD->setInlineSpecified(Record[Idx++]);
+  FD->setVirtualAsWritten(Record[Idx++]);
+  FD->setPure(Record[Idx++]);
+  FD->setHasInheritedPrototype(Record[Idx++]);
+  FD->setHasWrittenPrototype(Record[Idx++]);
+  FD->setDeleted(Record[Idx++]);
+  FD->setTrivial(Record[Idx++]);
+  FD->setCopyAssignment(Record[Idx++]);
+  FD->setHasImplicitReturnZero(Record[Idx++]);
+  FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  // FIXME: C++ TemplateOrInstantiation
+  unsigned NumParams = Record[Idx++];
+  llvm::SmallVector<ParmVarDecl *, 16> Params;
+  Params.reserve(NumParams);
+  for (unsigned I = 0; I != NumParams; ++I)
+    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+  FD->setParams(*Reader.getContext(), Params.data(), NumParams);
+}
+
+void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+  VisitNamedDecl(MD);
+  if (Record[Idx++]) {
+    // In practice, this won't be executed (since method definitions
+    // don't occur in header files).
+    MD->setBody(Reader.ReadDeclStmt());
+    MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
+    MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
+  }
+  MD->setInstanceMethod(Record[Idx++]);
+  MD->setVariadic(Record[Idx++]);
+  MD->setSynthesized(Record[Idx++]);
+  MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
+  MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
+  MD->setResultType(Reader.GetType(Record[Idx++]));
+  MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  unsigned NumParams = Record[Idx++];
+  llvm::SmallVector<ParmVarDecl *, 16> Params;
+  Params.reserve(NumParams);
+  for (unsigned I = 0; I != NumParams; ++I)
+    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+  MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams);
+}
+
+void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
+  VisitNamedDecl(CD);
+  SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]);
+  SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]);
+  CD->setAtEndRange(SourceRange(A, B));
+}
+
+void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
+  VisitObjCContainerDecl(ID);
+  ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
+  ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
+                       (Reader.GetDecl(Record[Idx++])));
+  unsigned NumProtocols = Record[Idx++];
+  llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
+  Protocols.reserve(NumProtocols);
+  for (unsigned I = 0; I != NumProtocols; ++I)
+    Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtocols);
+  for (unsigned I = 0; I != NumProtocols; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
+                      *Reader.getContext());
+  unsigned NumIvars = Record[Idx++];
+  llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
+  IVars.reserve(NumIvars);
+  for (unsigned I = 0; I != NumIvars; ++I)
+    IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+  ID->setIVarList(IVars.data(), NumIvars, *Reader.getContext());
+  ID->setCategoryList(
+               cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+  ID->setForwardDecl(Record[Idx++]);
+  ID->setImplicitInterfaceDecl(Record[Idx++]);
+  ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
+void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
+  VisitFieldDecl(IVD);
+  IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
+}
+
+void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
+  VisitObjCContainerDecl(PD);
+  PD->setForwardDecl(Record[Idx++]);
+  PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  unsigned NumProtoRefs = Record[Idx++];
+  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+  ProtoRefs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                      *Reader.getContext());
+}
+
+void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
+  VisitFieldDecl(FD);
+}
+
+void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
+  VisitDecl(CD);
+  unsigned NumClassRefs = Record[Idx++];
+  llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs;
+  ClassRefs.reserve(NumClassRefs);
+  for (unsigned I = 0; I != NumClassRefs; ++I)
+    ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+  llvm::SmallVector<SourceLocation, 16> SLocs;
+  SLocs.reserve(NumClassRefs);
+  for (unsigned I = 0; I != NumClassRefs; ++I)
+    SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
+                   NumClassRefs);
+}
+
+void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
+  VisitDecl(FPD);
+  unsigned NumProtoRefs = Record[Idx++];
+  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+  ProtoRefs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                       *Reader.getContext());
+}
+
+void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
+  VisitObjCContainerDecl(CD);
+  CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+  unsigned NumProtoRefs = Record[Idx++];
+  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+  ProtoRefs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                      *Reader.getContext());
+  CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+  CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
+void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
+  VisitNamedDecl(CAD);
+  CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+  VisitNamedDecl(D);
+  D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  D->setType(Reader.GetType(Record[Idx++]));
+  // FIXME: stable encoding
+  D->setPropertyAttributes(
+                      (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
+  // FIXME: stable encoding
+  D->setPropertyImplementation(
+                            (ObjCPropertyDecl::PropertyControl)Record[Idx++]);
+  D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
+  D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
+  D->setGetterMethodDecl(
+                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+  D->setSetterMethodDecl(
+                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+  D->setPropertyIvarDecl(
+                   cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
+  VisitObjCContainerDecl(D);
+  D->setClassInterface(
+              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+  VisitObjCImplDecl(D);
+  D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx));
+}
+
+void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+  VisitObjCImplDecl(D);
+  D->setSuperClass(
+              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+
+void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+  VisitDecl(D);
+  D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  D->setPropertyDecl(
+               cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
+  D->setPropertyIvarDecl(
+                   cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
+  VisitDeclaratorDecl(FD);
+  FD->setMutable(Record[Idx++]);
+  if (Record[Idx++])
+    FD->setBitWidth(Reader.ReadDeclExpr());
+}
+
+void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
+  VisitDeclaratorDecl(VD);
+  VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
+  VD->setThreadSpecified(Record[Idx++]);
+  VD->setCXXDirectInitializer(Record[Idx++]);
+  VD->setDeclaredInCondition(Record[Idx++]);
+  VD->setPreviousDeclaration(
+                         cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+  if (Record[Idx++])
+    VD->setInit(*Reader.getContext(), Reader.ReadDeclExpr());
+}
+
+void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
+  VisitVarDecl(PD);
+}
+
+void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
+  VisitVarDecl(PD);
+  PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
+}
+
+void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
+  VisitDecl(AD);
+  AD->setAsmString(cast<StringLiteral>(Reader.ReadDeclExpr()));
+}
+
+void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
+  VisitDecl(BD);
+  BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadDeclStmt()));
+  unsigned NumParams = Record[Idx++];
+  llvm::SmallVector<ParmVarDecl *, 16> Params;
+  Params.reserve(NumParams);
+  for (unsigned I = 0; I != NumParams; ++I)
+    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+  BD->setParams(*Reader.getContext(), Params.data(), NumParams);
+}
+
+std::pair<uint64_t, uint64_t>
+PCHDeclReader::VisitDeclContext(DeclContext *DC) {
+  uint64_t LexicalOffset = Record[Idx++];
+  uint64_t VisibleOffset = Record[Idx++];
+  return std::make_pair(LexicalOffset, VisibleOffset);
+}
+
+//===----------------------------------------------------------------------===//
+// Attribute Reading
+//===----------------------------------------------------------------------===//
+
+/// \brief Reads attributes from the current stream position.
+Attr *PCHReader::ReadAttributes() {
+  unsigned Code = DeclsCursor.ReadCode();
+  assert(Code == llvm::bitc::UNABBREV_RECORD &&
+         "Expected unabbreviated record"); (void)Code;
+
+  RecordData Record;
+  unsigned Idx = 0;
+  unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
+  assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
+  (void)RecCode;
+
+#define SIMPLE_ATTR(Name)                       \
+ case Attr::Name:                               \
+   New = ::new (*Context) Name##Attr();         \
+   break
+
+#define STRING_ATTR(Name)                                       \
+ case Attr::Name:                                               \
+   New = ::new (*Context) Name##Attr(ReadString(Record, Idx));  \
+   break
+
+#define UNSIGNED_ATTR(Name)                             \
+ case Attr::Name:                                       \
+   New = ::new (*Context) Name##Attr(Record[Idx++]);    \
+   break
+
+  Attr *Attrs = 0;
+  while (Idx < Record.size()) {
+    Attr *New = 0;
+    Attr::Kind Kind = (Attr::Kind)Record[Idx++];
+    bool IsInherited = Record[Idx++];
+
+    switch (Kind) {
+    default:
+      assert(0 && "Unknown attribute!");
+      break;
+    STRING_ATTR(Alias);
+    UNSIGNED_ATTR(Aligned);
+    SIMPLE_ATTR(AlwaysInline);
+    SIMPLE_ATTR(AnalyzerNoReturn);
+    STRING_ATTR(Annotate);
+    STRING_ATTR(AsmLabel);
+    SIMPLE_ATTR(BaseCheck);
+
+    case Attr::Blocks:
+      New = ::new (*Context) BlocksAttr(
+                                  (BlocksAttr::BlocksAttrTypes)Record[Idx++]);
+      break;
+
+    SIMPLE_ATTR(CDecl);
+
+    case Attr::Cleanup:
+      New = ::new (*Context) CleanupAttr(
+                                  cast<FunctionDecl>(GetDecl(Record[Idx++])));
+      break;
+
+    SIMPLE_ATTR(Const);
+    UNSIGNED_ATTR(Constructor);
+    SIMPLE_ATTR(DLLExport);
+    SIMPLE_ATTR(DLLImport);
+    SIMPLE_ATTR(Deprecated);
+    UNSIGNED_ATTR(Destructor);
+    SIMPLE_ATTR(FastCall);
+    SIMPLE_ATTR(Final);
+
+    case Attr::Format: {
+      std::string Type = ReadString(Record, Idx);
+      unsigned FormatIdx = Record[Idx++];
+      unsigned FirstArg = Record[Idx++];
+      New = ::new (*Context) FormatAttr(Type, FormatIdx, FirstArg);
+      break;
+    }
+
+    case Attr::FormatArg: {
+      unsigned FormatIdx = Record[Idx++];
+      New = ::new (*Context) FormatArgAttr(FormatIdx);
+      break;
+    }
+
+    case Attr::Sentinel: {
+      int sentinel = Record[Idx++];
+      int nullPos = Record[Idx++];
+      New = ::new (*Context) SentinelAttr(sentinel, nullPos);
+      break;
+    }
+
+    SIMPLE_ATTR(GNUInline);
+    SIMPLE_ATTR(Hiding);
+
+    case Attr::IBOutletKind:
+      New = ::new (*Context) IBOutletAttr();
+      break;
+
+    SIMPLE_ATTR(Malloc);
+    SIMPLE_ATTR(NoDebug);
+    SIMPLE_ATTR(NoInline);
+    SIMPLE_ATTR(NoReturn);
+    SIMPLE_ATTR(NoThrow);
+
+    case Attr::NonNull: {
+      unsigned Size = Record[Idx++];
+      llvm::SmallVector<unsigned, 16> ArgNums;
+      ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
+      Idx += Size;
+      New = ::new (*Context) NonNullAttr(ArgNums.data(), Size);
+      break;
+    }
+
+    case Attr::ReqdWorkGroupSize: {
+      unsigned X = Record[Idx++];
+      unsigned Y = Record[Idx++];
+      unsigned Z = Record[Idx++];
+      New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
+      break;
+    }
+
+    SIMPLE_ATTR(ObjCException);
+    SIMPLE_ATTR(ObjCNSObject);
+    SIMPLE_ATTR(CFReturnsRetained);
+    SIMPLE_ATTR(NSReturnsRetained);
+    SIMPLE_ATTR(Overloadable);
+    SIMPLE_ATTR(Override);
+    SIMPLE_ATTR(Packed);
+    UNSIGNED_ATTR(PragmaPack);
+    SIMPLE_ATTR(Pure);
+    UNSIGNED_ATTR(Regparm);
+    STRING_ATTR(Section);
+    SIMPLE_ATTR(StdCall);
+    SIMPLE_ATTR(TransparentUnion);
+    SIMPLE_ATTR(Unavailable);
+    SIMPLE_ATTR(Unused);
+    SIMPLE_ATTR(Used);
+
+    case Attr::Visibility:
+      New = ::new (*Context) VisibilityAttr(
+                              (VisibilityAttr::VisibilityTypes)Record[Idx++]);
+      break;
+
+    SIMPLE_ATTR(WarnUnusedResult);
+    SIMPLE_ATTR(Weak);
+    SIMPLE_ATTR(WeakImport);
+    }
+
+    assert(New && "Unable to decode attribute?");
+    New->setInherited(IsInherited);
+    New->setNext(Attrs);
+    Attrs = New;
+  }
+#undef UNSIGNED_ATTR
+#undef STRING_ATTR
+#undef SIMPLE_ATTR
+
+  // The list of attributes was built backwards. Reverse the list
+  // before returning it.
+  Attr *PrevAttr = 0, *NextAttr = 0;
+  while (Attrs) {
+    NextAttr = Attrs->getNext();
+    Attrs->setNext(PrevAttr);
+    PrevAttr = Attrs;
+    Attrs = NextAttr;
+  }
+
+  return PrevAttr;
+}
+
+//===----------------------------------------------------------------------===//
+// PCHReader Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Note that we have loaded the declaration with the given
+/// Index.
+///
+/// This routine notes that this declaration has already been loaded,
+/// so that future GetDecl calls will return this declaration rather
+/// than trying to load a new declaration.
+inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
+  assert(!DeclsLoaded[Index] && "Decl loaded twice?");
+  DeclsLoaded[Index] = D;
+}
+
+
+/// \brief Determine whether the consumer will be interested in seeing
+/// this declaration (via HandleTopLevelDecl).
+///
+/// This routine should return true for anything that might affect
+/// code generation, e.g., inline function definitions, Objective-C
+/// declarations with metadata, etc.
+static bool isConsumerInterestedIn(Decl *D) {
+  if (isa<FileScopeAsmDecl>(D))
+    return true;
+  if (VarDecl *Var = dyn_cast<VarDecl>(D))
+    return Var->isFileVarDecl() && Var->getInit();
+  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
+    return Func->isThisDeclarationADefinition();
+  return isa<ObjCProtocolDecl>(D);
+}
+
+/// \brief Read the declaration at the given offset from the PCH file.
+Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this declaration.
+  SavedStreamPosition SavedPosition(DeclsCursor);
+
+  // Note that we are loading a declaration record.
+  LoadingTypeOrDecl Loading(*this);
+
+  DeclsCursor.JumpToBit(Offset);
+  RecordData Record;
+  unsigned Code = DeclsCursor.ReadCode();
+  unsigned Idx = 0;
+  PCHDeclReader Reader(*this, Record, Idx);
+
+  Decl *D = 0;
+  switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
+  case pch::DECL_ATTR:
+  case pch::DECL_CONTEXT_LEXICAL:
+  case pch::DECL_CONTEXT_VISIBLE:
+    assert(false && "Record cannot be de-serialized with ReadDeclRecord");
+    break;
+  case pch::DECL_TRANSLATION_UNIT:
+    assert(Index == 0 && "Translation unit must be at index 0");
+    D = Context->getTranslationUnitDecl();
+    break;
+  case pch::DECL_TYPEDEF:
+    D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+    break;
+  case pch::DECL_ENUM:
+    D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), 0);
+    break;
+  case pch::DECL_RECORD:
+    D = RecordDecl::Create(*Context, TagDecl::TK_struct, 0, SourceLocation(),
+                           0, SourceLocation(), 0);
+    break;
+  case pch::DECL_ENUM_CONSTANT:
+    D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
+                                 0, llvm::APSInt());
+    break;
+  case pch::DECL_FUNCTION:
+    D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
+                             QualType(), 0);
+    break;
+  case pch::DECL_OBJC_METHOD:
+    D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),
+                               Selector(), QualType(), 0);
+    break;
+  case pch::DECL_OBJC_INTERFACE:
+    D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0);
+    break;
+  case pch::DECL_OBJC_IVAR:
+    D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
+                             ObjCIvarDecl::None);
+    break;
+  case pch::DECL_OBJC_PROTOCOL:
+    D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0);
+    break;
+  case pch::DECL_OBJC_AT_DEFS_FIELD:
+    D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0,
+                                    QualType(), 0);
+    break;
+  case pch::DECL_OBJC_CLASS:
+    D = ObjCClassDecl::Create(*Context, 0, SourceLocation());
+    break;
+  case pch::DECL_OBJC_FORWARD_PROTOCOL:
+    D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
+    break;
+  case pch::DECL_OBJC_CATEGORY:
+    D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), 
+                                 SourceLocation(), SourceLocation(), 0);
+    break;
+  case pch::DECL_OBJC_CATEGORY_IMPL:
+    D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+    break;
+  case pch::DECL_OBJC_IMPLEMENTATION:
+    D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+    break;
+  case pch::DECL_OBJC_COMPATIBLE_ALIAS:
+    D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+    break;
+  case pch::DECL_OBJC_PROPERTY:
+    D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
+                                 QualType());
+    break;
+  case pch::DECL_OBJC_PROPERTY_IMPL:
+    D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),
+                                     SourceLocation(), 0,
+                                     ObjCPropertyImplDecl::Dynamic, 0);
+    break;
+  case pch::DECL_FIELD:
+    D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,
+                          false);
+    break;
+  case pch::DECL_VAR:
+    D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
+                        VarDecl::None);
+    break;
+
+  case pch::DECL_IMPLICIT_PARAM:
+    D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
+    break;
+
+  case pch::DECL_PARM_VAR:
+    D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
+                            VarDecl::None, 0);
+    break;
+  case pch::DECL_FILE_SCOPE_ASM:
+    D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
+    break;
+  case pch::DECL_BLOCK:
+    D = BlockDecl::Create(*Context, 0, SourceLocation());
+    break;
+  }
+
+  assert(D && "Unknown declaration reading PCH file");
+  LoadedDecl(Index, D);
+  Reader.Visit(D);
+
+  // If this declaration is also a declaration context, get the
+  // offsets for its tables of lexical and visible declarations.
+  if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
+    std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
+    if (Offsets.first || Offsets.second) {
+      DC->setHasExternalLexicalStorage(Offsets.first != 0);
+      DC->setHasExternalVisibleStorage(Offsets.second != 0);
+      DeclContextOffsets[DC] = Offsets;
+    }
+  }
+  assert(Idx == Record.size());
+
+  // If we have deserialized a declaration that has a definition the
+  // AST consumer might need to know about, notify the consumer
+  // about that definition now or queue it for later.
+  if (isConsumerInterestedIn(D)) {
+    if (Consumer) {
+      DeclGroupRef DG(D);
+      Consumer->HandleTopLevelDecl(DG);
+    } else {
+      InterestingDecls.push_back(D);
+    }
+  }
+
+  return D;
+}
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
new file mode 100644
index 0000000..d123694
--- /dev/null
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -0,0 +1,1281 @@
+//===--- PCHReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Statement/expression deserialization.  This implements the
+// PCHReader::ReadStmt method.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHReader.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/StmtVisitor.h"
+using namespace clang;
+
+namespace {
+  class PCHStmtReader : public StmtVisitor<PCHStmtReader, unsigned> {
+    PCHReader &Reader;
+    const PCHReader::RecordData &Record;
+    unsigned &Idx;
+    llvm::SmallVectorImpl<Stmt *> &StmtStack;
+
+  public:
+    PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record,
+                  unsigned &Idx, llvm::SmallVectorImpl<Stmt *> &StmtStack)
+      : Reader(Reader), Record(Record), Idx(Idx), StmtStack(StmtStack) { }
+
+    /// \brief The number of record fields required for the Stmt class
+    /// itself.
+    static const unsigned NumStmtFields = 0;
+
+    /// \brief The number of record fields required for the Expr class
+    /// itself.
+    static const unsigned NumExprFields = NumStmtFields + 3;
+
+    // Each of the Visit* functions reads in part of the expression
+    // from the given record and the current expression stack, then
+    // return the total number of operands that it read from the
+    // expression stack.
+
+    unsigned VisitStmt(Stmt *S);
+    unsigned VisitNullStmt(NullStmt *S);
+    unsigned VisitCompoundStmt(CompoundStmt *S);
+    unsigned VisitSwitchCase(SwitchCase *S);
+    unsigned VisitCaseStmt(CaseStmt *S);
+    unsigned VisitDefaultStmt(DefaultStmt *S);
+    unsigned VisitLabelStmt(LabelStmt *S);
+    unsigned VisitIfStmt(IfStmt *S);
+    unsigned VisitSwitchStmt(SwitchStmt *S);
+    unsigned VisitWhileStmt(WhileStmt *S);
+    unsigned VisitDoStmt(DoStmt *S);
+    unsigned VisitForStmt(ForStmt *S);
+    unsigned VisitGotoStmt(GotoStmt *S);
+    unsigned VisitIndirectGotoStmt(IndirectGotoStmt *S);
+    unsigned VisitContinueStmt(ContinueStmt *S);
+    unsigned VisitBreakStmt(BreakStmt *S);
+    unsigned VisitReturnStmt(ReturnStmt *S);
+    unsigned VisitDeclStmt(DeclStmt *S);
+    unsigned VisitAsmStmt(AsmStmt *S);
+    unsigned VisitExpr(Expr *E);
+    unsigned VisitPredefinedExpr(PredefinedExpr *E);
+    unsigned VisitDeclRefExpr(DeclRefExpr *E);
+    unsigned VisitIntegerLiteral(IntegerLiteral *E);
+    unsigned VisitFloatingLiteral(FloatingLiteral *E);
+    unsigned VisitImaginaryLiteral(ImaginaryLiteral *E);
+    unsigned VisitStringLiteral(StringLiteral *E);
+    unsigned VisitCharacterLiteral(CharacterLiteral *E);
+    unsigned VisitParenExpr(ParenExpr *E);
+    unsigned VisitUnaryOperator(UnaryOperator *E);
+    unsigned VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+    unsigned VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+    unsigned VisitCallExpr(CallExpr *E);
+    unsigned VisitMemberExpr(MemberExpr *E);
+    unsigned VisitCastExpr(CastExpr *E);
+    unsigned VisitBinaryOperator(BinaryOperator *E);
+    unsigned VisitCompoundAssignOperator(CompoundAssignOperator *E);
+    unsigned VisitConditionalOperator(ConditionalOperator *E);
+    unsigned VisitImplicitCastExpr(ImplicitCastExpr *E);
+    unsigned VisitExplicitCastExpr(ExplicitCastExpr *E);
+    unsigned VisitCStyleCastExpr(CStyleCastExpr *E);
+    unsigned VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+    unsigned VisitExtVectorElementExpr(ExtVectorElementExpr *E);
+    unsigned VisitInitListExpr(InitListExpr *E);
+    unsigned VisitDesignatedInitExpr(DesignatedInitExpr *E);
+    unsigned VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+    unsigned VisitVAArgExpr(VAArgExpr *E);
+    unsigned VisitAddrLabelExpr(AddrLabelExpr *E);
+    unsigned VisitStmtExpr(StmtExpr *E);
+    unsigned VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
+    unsigned VisitChooseExpr(ChooseExpr *E);
+    unsigned VisitGNUNullExpr(GNUNullExpr *E);
+    unsigned VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+    unsigned VisitBlockExpr(BlockExpr *E);
+    unsigned VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
+    unsigned VisitObjCStringLiteral(ObjCStringLiteral *E);
+    unsigned VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+    unsigned VisitObjCSelectorExpr(ObjCSelectorExpr *E);
+    unsigned VisitObjCProtocolExpr(ObjCProtocolExpr *E);
+    unsigned VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
+    unsigned VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
+    unsigned VisitObjCImplicitSetterGetterRefExpr(
+                            ObjCImplicitSetterGetterRefExpr *E);
+    unsigned VisitObjCMessageExpr(ObjCMessageExpr *E);
+    unsigned VisitObjCSuperExpr(ObjCSuperExpr *E);
+    unsigned VisitObjCIsaExpr(ObjCIsaExpr *E);
+
+    unsigned VisitObjCForCollectionStmt(ObjCForCollectionStmt *);
+    unsigned VisitObjCAtCatchStmt(ObjCAtCatchStmt *);
+    unsigned VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *);
+    unsigned VisitObjCAtTryStmt(ObjCAtTryStmt *);
+    unsigned VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
+    unsigned VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
+
+    unsigned VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+    unsigned VisitCXXConstructExpr(CXXConstructExpr *E);
+    unsigned VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+    unsigned VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
+    unsigned VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
+    unsigned VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
+    unsigned VisitCXXConstCastExpr(CXXConstCastExpr *E);
+    unsigned VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
+    unsigned VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+    unsigned VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+  };
+}
+
+unsigned PCHStmtReader::VisitStmt(Stmt *S) {
+  assert(Idx == NumStmtFields && "Incorrect statement field count");
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitNullStmt(NullStmt *S) {
+  VisitStmt(S);
+  S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) {
+  VisitStmt(S);
+  unsigned NumStmts = Record[Idx++];
+  S->setStmts(*Reader.getContext(),
+              StmtStack.data() + StmtStack.size() - NumStmts, NumStmts);
+  S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return NumStmts;
+}
+
+unsigned PCHStmtReader::VisitSwitchCase(SwitchCase *S) {
+  VisitStmt(S);
+  Reader.RecordSwitchCaseID(S, Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCaseStmt(CaseStmt *S) {
+  VisitSwitchCase(S);
+  S->setLHS(cast<Expr>(StmtStack[StmtStack.size() - 3]));
+  S->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setSubStmt(StmtStack.back());
+  S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setEllipsisLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) {
+  VisitSwitchCase(S);
+  S->setSubStmt(StmtStack.back());
+  S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitLabelStmt(LabelStmt *S) {
+  VisitStmt(S);
+  S->setID(Reader.GetIdentifierInfo(Record, Idx));
+  S->setSubStmt(StmtStack.back());
+  S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  Reader.RecordLabelStmt(S, Record[Idx++]);
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) {
+  VisitStmt(S);
+  S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+  S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
+  S->setThen(StmtStack[StmtStack.size() - 2]);
+  S->setElse(StmtStack[StmtStack.size() - 1]);
+  S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setElseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
+  VisitStmt(S);
+  S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+  S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setBody(StmtStack.back());
+  S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  SwitchCase *PrevSC = 0;
+  for (unsigned N = Record.size(); Idx != N; ++Idx) {
+    SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
+    if (PrevSC)
+      PrevSC->setNextSwitchCase(SC);
+    else
+      S->setSwitchCaseList(SC);
+
+    // Retain this SwitchCase, since SwitchStmt::addSwitchCase() would
+    // normally retain it (but we aren't calling addSwitchCase).
+    SC->Retain();
+    PrevSC = SC;
+  }
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitWhileStmt(WhileStmt *S) {
+  VisitStmt(S);
+  S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+  S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setBody(StmtStack.back());
+  S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitDoStmt(DoStmt *S) {
+  VisitStmt(S);
+  S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setBody(StmtStack.back());
+  S->setDoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitForStmt(ForStmt *S) {
+  VisitStmt(S);
+  S->setInit(StmtStack[StmtStack.size() - 4]);
+  S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 3]));
+  S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+  S->setInc(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setBody(StmtStack.back());
+  S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 4;
+}
+
+unsigned PCHStmtReader::VisitGotoStmt(GotoStmt *S) {
+  VisitStmt(S);
+  Reader.SetLabelOf(S, Record[Idx++]);
+  S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+  VisitStmt(S);
+  S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setTarget(cast_or_null<Expr>(StmtStack.back()));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitContinueStmt(ContinueStmt *S) {
+  VisitStmt(S);
+  S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitBreakStmt(BreakStmt *S) {
+  VisitStmt(S);
+  S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitReturnStmt(ReturnStmt *S) {
+  VisitStmt(S);
+  S->setRetValue(cast_or_null<Expr>(StmtStack.back()));
+  S->setReturnLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitDeclStmt(DeclStmt *S) {
+  VisitStmt(S);
+  S->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+
+  if (Idx + 1 == Record.size()) {
+    // Single declaration
+    S->setDeclGroup(DeclGroupRef(Reader.GetDecl(Record[Idx++])));
+  } else {
+    llvm::SmallVector<Decl *, 16> Decls;
+    Decls.reserve(Record.size() - Idx);
+    for (unsigned N = Record.size(); Idx != N; ++Idx)
+      Decls.push_back(Reader.GetDecl(Record[Idx]));
+    S->setDeclGroup(DeclGroupRef(DeclGroup::Create(*Reader.getContext(),
+                                                   Decls.data(),
+                                                   Decls.size())));
+  }
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitAsmStmt(AsmStmt *S) {
+  VisitStmt(S);
+  unsigned NumOutputs = Record[Idx++];
+  unsigned NumInputs = Record[Idx++];
+  unsigned NumClobbers = Record[Idx++];
+  S->setAsmLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setVolatile(Record[Idx++]);
+  S->setSimple(Record[Idx++]);
+  S->setMSAsm(Record[Idx++]);
+
+  unsigned StackIdx
+    = StmtStack.size() - (NumOutputs*2 + NumInputs*2 + NumClobbers + 1);
+  S->setAsmString(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
+
+  // Outputs and inputs
+  llvm::SmallVector<IdentifierInfo *, 16> Names;
+  llvm::SmallVector<StringLiteral*, 16> Constraints;
+  llvm::SmallVector<Stmt*, 16> Exprs;
+  for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
+    Names.push_back(Reader.GetIdentifierInfo(Record, Idx));
+    Constraints.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
+    Exprs.push_back(StmtStack[StackIdx++]);
+  }
+
+  // Constraints
+  llvm::SmallVector<StringLiteral*, 16> Clobbers;
+  for (unsigned I = 0; I != NumClobbers; ++I)
+    Clobbers.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
+
+  S->setOutputsAndInputsAndClobbers(*Reader.getContext(),
+                                    Names.data(), Constraints.data(), 
+                                    Exprs.data(), NumOutputs, NumInputs, 
+                                    Clobbers.data(), NumClobbers);
+
+  assert(StackIdx == StmtStack.size() && "Error deserializing AsmStmt");
+  return NumOutputs*2 + NumInputs*2 + NumClobbers + 1;
+}
+
+unsigned PCHStmtReader::VisitExpr(Expr *E) {
+  VisitStmt(E);
+  E->setType(Reader.GetType(Record[Idx++]));
+  E->setTypeDependent(Record[Idx++]);
+  E->setValueDependent(Record[Idx++]);
+  assert(Idx == NumExprFields && "Incorrect expression field count");
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
+  VisitExpr(E);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
+  VisitExpr(E);
+  E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  // FIXME: read qualifier
+  // FIXME: read explicit template arguments
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
+  VisitExpr(E);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setValue(Reader.ReadAPInt(Record, Idx));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
+  VisitExpr(E);
+  E->setValue(Reader.ReadAPFloat(Record, Idx));
+  E->setExact(Record[Idx++]);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+  VisitExpr(E);
+  E->setSubExpr(cast<Expr>(StmtStack.back()));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitStringLiteral(StringLiteral *E) {
+  VisitExpr(E);
+  unsigned Len = Record[Idx++];
+  assert(Record[Idx] == E->getNumConcatenated() &&
+         "Wrong number of concatenated tokens!");
+  ++Idx;
+  E->setWide(Record[Idx++]);
+
+  // Read string data
+  llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len);
+  E->setString(*Reader.getContext(), Str.str());
+  Idx += Len;
+
+  // Read source locations
+  for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
+    E->setStrTokenLoc(I, SourceLocation::getFromRawEncoding(Record[Idx++]));
+
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
+  VisitExpr(E);
+  E->setValue(Record[Idx++]);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setWide(Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitParenExpr(ParenExpr *E) {
+  VisitExpr(E);
+  E->setLParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setSubExpr(cast<Expr>(StmtStack.back()));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) {
+  VisitExpr(E);
+  E->setSubExpr(cast<Expr>(StmtStack.back()));
+  E->setOpcode((UnaryOperator::Opcode)Record[Idx++]);
+  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+  VisitExpr(E);
+  E->setSizeof(Record[Idx++]);
+  if (Record[Idx] == 0) {
+    E->setArgument(cast<Expr>(StmtStack.back()));
+    ++Idx;
+  } else {
+    E->setArgument(Reader.GetTypeSourceInfo(Record, Idx));
+  }
+  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return E->isArgumentType()? 0 : 1;
+}
+
+unsigned PCHStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+  VisitExpr(E);
+  E->setLHS(cast<Expr>(StmtStack[StmtStack.size() - 2]));
+  E->setRHS(cast<Expr>(StmtStack[StmtStack.size() - 1]));
+  E->setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitCallExpr(CallExpr *E) {
+  VisitExpr(E);
+  E->setNumArgs(*Reader.getContext(), Record[Idx++]);
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setCallee(cast<Expr>(StmtStack[StmtStack.size() - E->getNumArgs() - 1]));
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+    E->setArg(I, cast<Expr>(StmtStack[StmtStack.size() - N + I]));
+  return E->getNumArgs() + 1;
+}
+
+unsigned PCHStmtReader::VisitMemberExpr(MemberExpr *E) {
+  VisitExpr(E);
+  E->setBase(cast<Expr>(StmtStack.back()));
+  E->setMemberDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setArrow(Record[Idx++]);
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
+  VisitExpr(E);
+  E->setBase(cast<Expr>(StmtStack.back()));
+  E->setIsaMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setArrow(Record[Idx++]);
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitCastExpr(CastExpr *E) {
+  VisitExpr(E);
+  E->setSubExpr(cast<Expr>(StmtStack.back()));
+  E->setCastKind((CastExpr::CastKind)Record[Idx++]);
+
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) {
+  VisitExpr(E);
+  E->setLHS(cast<Expr>(StmtStack.end()[-2]));
+  E->setRHS(cast<Expr>(StmtStack.end()[-1]));
+  E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);
+  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+  VisitBinaryOperator(E);
+  E->setComputationLHSType(Reader.GetType(Record[Idx++]));
+  E->setComputationResultType(Reader.GetType(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
+  VisitExpr(E);
+  E->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
+  E->setLHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  E->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 1]));
+  E->setQuestionLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+  VisitCastExpr(E);
+  E->setLvalueCast(Record[Idx++]);
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+  VisitCastExpr(E);
+  E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(Record, Idx));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
+  VisitExplicitCastExpr(E);
+  E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+  VisitExpr(E);
+  E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+  E->setInitializer(cast<Expr>(StmtStack.back()));
+  E->setFileScope(Record[Idx++]);
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
+  VisitExpr(E);
+  E->setBase(cast<Expr>(StmtStack.back()));
+  E->setAccessor(Reader.GetIdentifierInfo(Record, Idx));
+  E->setAccessorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitInitListExpr(InitListExpr *E) {
+  VisitExpr(E);
+  unsigned NumInits = Record[Idx++];
+  E->reserveInits(NumInits);
+  for (unsigned I = 0; I != NumInits; ++I)
+    E->updateInit(I,
+                  cast<Expr>(StmtStack[StmtStack.size() - NumInits - 1 + I]));
+  E->setSyntacticForm(cast_or_null<InitListExpr>(StmtStack.back()));
+  E->setLBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setInitializedFieldInUnion(
+                      cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])));
+  E->sawArrayRangeDesignator(Record[Idx++]);
+  return NumInits + 1;
+}
+
+unsigned PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+  typedef DesignatedInitExpr::Designator Designator;
+
+  VisitExpr(E);
+  unsigned NumSubExprs = Record[Idx++];
+  assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs");
+  for (unsigned I = 0; I != NumSubExprs; ++I)
+    E->setSubExpr(I, cast<Expr>(StmtStack[StmtStack.size() - NumSubExprs + I]));
+  E->setEqualOrColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setGNUSyntax(Record[Idx++]);
+
+  llvm::SmallVector<Designator, 4> Designators;
+  while (Idx < Record.size()) {
+    switch ((pch::DesignatorTypes)Record[Idx++]) {
+    case pch::DESIG_FIELD_DECL: {
+      FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++]));
+      SourceLocation DotLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      SourceLocation FieldLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      Designators.push_back(Designator(Field->getIdentifier(), DotLoc,
+                                       FieldLoc));
+      Designators.back().setField(Field);
+      break;
+    }
+
+    case pch::DESIG_FIELD_NAME: {
+      const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx);
+      SourceLocation DotLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      SourceLocation FieldLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      Designators.push_back(Designator(Name, DotLoc, FieldLoc));
+      break;
+    }
+
+    case pch::DESIG_ARRAY: {
+      unsigned Index = Record[Idx++];
+      SourceLocation LBracketLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      SourceLocation RBracketLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc));
+      break;
+    }
+
+    case pch::DESIG_ARRAY_RANGE: {
+      unsigned Index = Record[Idx++];
+      SourceLocation LBracketLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      SourceLocation EllipsisLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      SourceLocation RBracketLoc
+        = SourceLocation::getFromRawEncoding(Record[Idx++]);
+      Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc,
+                                       RBracketLoc));
+      break;
+    }
+    }
+  }
+  E->setDesignators(*Reader.getContext(), 
+                    Designators.data(), Designators.size());
+
+  return NumSubExprs;
+}
+
+unsigned PCHStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+  VisitExpr(E);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitVAArgExpr(VAArgExpr *E) {
+  VisitExpr(E);
+  E->setSubExpr(cast<Expr>(StmtStack.back()));
+  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
+  VisitExpr(E);
+  E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  Reader.SetLabelOf(E, Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitStmtExpr(StmtExpr *E) {
+  VisitExpr(E);
+  E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setSubStmt(cast_or_null<CompoundStmt>(StmtStack.back()));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
+  VisitExpr(E);
+  E->setArgType1(Reader.GetType(Record[Idx++]));
+  E->setArgType2(Reader.GetType(Record[Idx++]));
+  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitChooseExpr(ChooseExpr *E) {
+  VisitExpr(E);
+  E->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
+  E->setLHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  E->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 1]));
+  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
+  VisitExpr(E);
+  E->setTokenLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+  VisitExpr(E);
+  unsigned NumExprs = Record[Idx++];
+  E->setExprs(*Reader.getContext(),
+              (Expr **)&StmtStack[StmtStack.size() - NumExprs], NumExprs);
+  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return NumExprs;
+}
+
+unsigned PCHStmtReader::VisitBlockExpr(BlockExpr *E) {
+  VisitExpr(E);
+  E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setHasBlockDeclRefExprs(Record[Idx++]);
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+  VisitExpr(E);
+  E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setByRef(Record[Idx++]);
+  E->setConstQualAdded(Record[Idx++]);
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Objective-C Expressions and Statements
+
+unsigned PCHStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) {
+  VisitExpr(E);
+  E->setString(cast<StringLiteral>(StmtStack.back()));
+  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+  VisitExpr(E);
+  E->setEncodedType(Reader.GetType(Record[Idx++]));
+  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+  VisitExpr(E);
+  E->setSelector(Reader.GetSelector(Record, Idx));
+  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+  VisitExpr(E);
+  E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  VisitExpr(E);
+  E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setBase(cast<Expr>(StmtStack.back()));
+  E->setIsArrow(Record[Idx++]);
+  E->setIsFreeIvar(Record[Idx++]);
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+  VisitExpr(E);
+  E->setProperty(cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setBase(cast<Expr>(StmtStack.back()));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr(
+                                      ObjCImplicitSetterGetterRefExpr *E) {
+  VisitExpr(E);
+  E->setGetterMethod(
+                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setSetterMethod(
+                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setInterfaceDecl(
+              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setBase(cast_or_null<Expr>(StmtStack.back()));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  VisitExpr(E);
+  E->setNumArgs(Record[Idx++]);
+  E->setLeftLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setSelector(Reader.GetSelector(Record, Idx));
+  E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+
+  E->setReceiver(
+         cast_or_null<Expr>(StmtStack[StmtStack.size() - E->getNumArgs() - 1]));
+  if (!E->getReceiver()) {
+    ObjCMessageExpr::ClassInfo CI;
+    CI.first = cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]));
+    CI.second = Reader.GetIdentifierInfo(Record, Idx);
+    E->setClassInfo(CI);
+  }
+
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+    E->setArg(I, cast<Expr>(StmtStack[StmtStack.size() - N + I]));
+  return E->getNumArgs() + 1;
+}
+
+unsigned PCHStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) {
+  VisitExpr(E);
+  E->setLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+  VisitStmt(S);
+  S->setElement(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 3]));
+  S->setCollection(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
+  S->setBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1]));
+  S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+  VisitStmt(S);
+  S->setCatchBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2]));
+  S->setNextCatchStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1]));
+  S->setCatchParamDecl(cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+  S->setAtCatchLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+  VisitStmt(S);
+  S->setFinallyBody(StmtStack.back());
+  S->setAtFinallyLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+unsigned PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+  VisitStmt(S);
+  S->setTryBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 3]));
+  S->setCatchStmts(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2]));
+  S->setFinallyStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1]));
+  S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 3;
+}
+
+unsigned PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+  VisitStmt(S);
+  S->setSynchExpr(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2]));
+  S->setSynchBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1]));
+  S->setAtSynchronizedLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 2;
+}
+
+unsigned PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+  VisitStmt(S);
+  S->setThrowExpr(StmtStack.back());
+  S->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 1;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions and Statements
+
+unsigned PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  unsigned num = VisitCallExpr(E);
+  E->setOperator((OverloadedOperatorKind)Record[Idx++]);
+  return num;
+}
+
+unsigned PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
+  VisitExpr(E);
+  E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setElidable(Record[Idx++]);  
+  E->setRequiresZeroInitialization(Record[Idx++]);
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+    E->setArg(I, cast<Expr>(StmtStack[StmtStack.size() - N + I]));
+  return E->getNumArgs();
+}
+
+unsigned PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+  unsigned num = VisitExplicitCastExpr(E);
+  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return num;
+}
+
+unsigned PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+  return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+  return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+  return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+  return VisitCXXNamedCastExpr(E);
+}
+
+unsigned PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+  unsigned num = VisitExplicitCastExpr(E);
+  E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return num;
+}
+
+unsigned PCHStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+  VisitExpr(E);
+  E->setValue(Record[Idx++]);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+unsigned PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+  VisitExpr(E);
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  return 0;
+}
+
+// Within the bitstream, expressions are stored in Reverse Polish
+// Notation, with each of the subexpressions preceding the
+// expression they are stored in. To evaluate expressions, we
+// continue reading expressions and placing them on the stack, with
+// expressions having operands removing those operands from the
+// stack. Evaluation terminates when we see a STMT_STOP record, and
+// the single remaining expression on the stack is our result.
+Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
+  RecordData Record;
+  unsigned Idx;
+  llvm::SmallVector<Stmt *, 16> StmtStack;
+  PCHStmtReader Reader(*this, Record, Idx, StmtStack);
+  Stmt::EmptyShell Empty;
+
+  while (true) {
+    unsigned Code = Cursor.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Cursor.ReadBlockEnd()) {
+        Error("error at end of block in PCH file");
+        return 0;
+      }
+      break;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Cursor.ReadSubBlockID();
+      if (Cursor.SkipBlock()) {
+        Error("malformed block record in PCH file");
+        return 0;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Cursor.ReadAbbrevRecord();
+      continue;
+    }
+
+    Stmt *S = 0;
+    Idx = 0;
+    Record.clear();
+    bool Finished = false;
+    switch ((pch::StmtCode)Cursor.ReadRecord(Code, Record)) {
+    case pch::STMT_STOP:
+      Finished = true;
+      break;
+
+    case pch::STMT_NULL_PTR:
+      S = 0;
+      break;
+
+    case pch::STMT_NULL:
+      S = new (Context) NullStmt(Empty);
+      break;
+
+    case pch::STMT_COMPOUND:
+      S = new (Context) CompoundStmt(Empty);
+      break;
+
+    case pch::STMT_CASE:
+      S = new (Context) CaseStmt(Empty);
+      break;
+
+    case pch::STMT_DEFAULT:
+      S = new (Context) DefaultStmt(Empty);
+      break;
+
+    case pch::STMT_LABEL:
+      S = new (Context) LabelStmt(Empty);
+      break;
+
+    case pch::STMT_IF:
+      S = new (Context) IfStmt(Empty);
+      break;
+
+    case pch::STMT_SWITCH:
+      S = new (Context) SwitchStmt(Empty);
+      break;
+
+    case pch::STMT_WHILE:
+      S = new (Context) WhileStmt(Empty);
+      break;
+
+    case pch::STMT_DO:
+      S = new (Context) DoStmt(Empty);
+      break;
+
+    case pch::STMT_FOR:
+      S = new (Context) ForStmt(Empty);
+      break;
+
+    case pch::STMT_GOTO:
+      S = new (Context) GotoStmt(Empty);
+      break;
+
+    case pch::STMT_INDIRECT_GOTO:
+      S = new (Context) IndirectGotoStmt(Empty);
+      break;
+
+    case pch::STMT_CONTINUE:
+      S = new (Context) ContinueStmt(Empty);
+      break;
+
+    case pch::STMT_BREAK:
+      S = new (Context) BreakStmt(Empty);
+      break;
+
+    case pch::STMT_RETURN:
+      S = new (Context) ReturnStmt(Empty);
+      break;
+
+    case pch::STMT_DECL:
+      S = new (Context) DeclStmt(Empty);
+      break;
+
+    case pch::STMT_ASM:
+      S = new (Context) AsmStmt(Empty);
+      break;
+
+    case pch::EXPR_PREDEFINED:
+      S = new (Context) PredefinedExpr(Empty);
+      break;
+
+    case pch::EXPR_DECL_REF:
+      S = new (Context) DeclRefExpr(Empty);
+      break;
+
+    case pch::EXPR_INTEGER_LITERAL:
+      S = new (Context) IntegerLiteral(Empty);
+      break;
+
+    case pch::EXPR_FLOATING_LITERAL:
+      S = new (Context) FloatingLiteral(Empty);
+      break;
+
+    case pch::EXPR_IMAGINARY_LITERAL:
+      S = new (Context) ImaginaryLiteral(Empty);
+      break;
+
+    case pch::EXPR_STRING_LITERAL:
+      S = StringLiteral::CreateEmpty(*Context,
+                                     Record[PCHStmtReader::NumExprFields + 1]);
+      break;
+
+    case pch::EXPR_CHARACTER_LITERAL:
+      S = new (Context) CharacterLiteral(Empty);
+      break;
+
+    case pch::EXPR_PAREN:
+      S = new (Context) ParenExpr(Empty);
+      break;
+
+    case pch::EXPR_UNARY_OPERATOR:
+      S = new (Context) UnaryOperator(Empty);
+      break;
+
+    case pch::EXPR_SIZEOF_ALIGN_OF:
+      S = new (Context) SizeOfAlignOfExpr(Empty);
+      break;
+
+    case pch::EXPR_ARRAY_SUBSCRIPT:
+      S = new (Context) ArraySubscriptExpr(Empty);
+      break;
+
+    case pch::EXPR_CALL:
+      S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty);
+      break;
+
+    case pch::EXPR_MEMBER:
+      S = new (Context) MemberExpr(Empty);
+      break;
+
+    case pch::EXPR_BINARY_OPERATOR:
+      S = new (Context) BinaryOperator(Empty);
+      break;
+
+    case pch::EXPR_COMPOUND_ASSIGN_OPERATOR:
+      S = new (Context) CompoundAssignOperator(Empty);
+      break;
+
+    case pch::EXPR_CONDITIONAL_OPERATOR:
+      S = new (Context) ConditionalOperator(Empty);
+      break;
+
+    case pch::EXPR_IMPLICIT_CAST:
+      S = new (Context) ImplicitCastExpr(Empty);
+      break;
+
+    case pch::EXPR_CSTYLE_CAST:
+      S = new (Context) CStyleCastExpr(Empty);
+      break;
+
+    case pch::EXPR_COMPOUND_LITERAL:
+      S = new (Context) CompoundLiteralExpr(Empty);
+      break;
+
+    case pch::EXPR_EXT_VECTOR_ELEMENT:
+      S = new (Context) ExtVectorElementExpr(Empty);
+      break;
+
+    case pch::EXPR_INIT_LIST:
+      S = new (Context) InitListExpr(Empty);
+      break;
+
+    case pch::EXPR_DESIGNATED_INIT:
+      S = DesignatedInitExpr::CreateEmpty(*Context,
+                                     Record[PCHStmtReader::NumExprFields] - 1);
+
+      break;
+
+    case pch::EXPR_IMPLICIT_VALUE_INIT:
+      S = new (Context) ImplicitValueInitExpr(Empty);
+      break;
+
+    case pch::EXPR_VA_ARG:
+      S = new (Context) VAArgExpr(Empty);
+      break;
+
+    case pch::EXPR_ADDR_LABEL:
+      S = new (Context) AddrLabelExpr(Empty);
+      break;
+
+    case pch::EXPR_STMT:
+      S = new (Context) StmtExpr(Empty);
+      break;
+
+    case pch::EXPR_TYPES_COMPATIBLE:
+      S = new (Context) TypesCompatibleExpr(Empty);
+      break;
+
+    case pch::EXPR_CHOOSE:
+      S = new (Context) ChooseExpr(Empty);
+      break;
+
+    case pch::EXPR_GNU_NULL:
+      S = new (Context) GNUNullExpr(Empty);
+      break;
+
+    case pch::EXPR_SHUFFLE_VECTOR:
+      S = new (Context) ShuffleVectorExpr(Empty);
+      break;
+
+    case pch::EXPR_BLOCK:
+      S = new (Context) BlockExpr(Empty);
+      break;
+
+    case pch::EXPR_BLOCK_DECL_REF:
+      S = new (Context) BlockDeclRefExpr(Empty);
+      break;
+
+    case pch::EXPR_OBJC_STRING_LITERAL:
+      S = new (Context) ObjCStringLiteral(Empty);
+      break;
+    case pch::EXPR_OBJC_ENCODE:
+      S = new (Context) ObjCEncodeExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_SELECTOR_EXPR:
+      S = new (Context) ObjCSelectorExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_PROTOCOL_EXPR:
+      S = new (Context) ObjCProtocolExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_IVAR_REF_EXPR:
+      S = new (Context) ObjCIvarRefExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_PROPERTY_REF_EXPR:
+      S = new (Context) ObjCPropertyRefExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_KVC_REF_EXPR:
+      S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_MESSAGE_EXPR:
+      S = new (Context) ObjCMessageExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_SUPER_EXPR:
+      S = new (Context) ObjCSuperExpr(Empty);
+      break;
+    case pch::EXPR_OBJC_ISA:
+      S = new (Context) ObjCIsaExpr(Empty);
+      break;
+    case pch::STMT_OBJC_FOR_COLLECTION:
+      S = new (Context) ObjCForCollectionStmt(Empty);
+      break;
+    case pch::STMT_OBJC_CATCH:
+      S = new (Context) ObjCAtCatchStmt(Empty);
+      break;
+    case pch::STMT_OBJC_FINALLY:
+      S = new (Context) ObjCAtFinallyStmt(Empty);
+      break;
+    case pch::STMT_OBJC_AT_TRY:
+      S = new (Context) ObjCAtTryStmt(Empty);
+      break;
+    case pch::STMT_OBJC_AT_SYNCHRONIZED:
+      S = new (Context) ObjCAtSynchronizedStmt(Empty);
+      break;
+    case pch::STMT_OBJC_AT_THROW:
+      S = new (Context) ObjCAtThrowStmt(Empty);
+      break;
+
+    case pch::EXPR_CXX_OPERATOR_CALL:
+      S = new (Context) CXXOperatorCallExpr(*Context, Empty);
+      break;
+        
+    case pch::EXPR_CXX_CONSTRUCT:
+      S = new (Context) CXXConstructExpr(Empty, *Context,
+                                      Record[PCHStmtReader::NumExprFields + 2]);
+      break;
+
+    case pch::EXPR_CXX_STATIC_CAST:
+      S = new (Context) CXXStaticCastExpr(Empty);
+      break;
+
+    case pch::EXPR_CXX_DYNAMIC_CAST:
+      S = new (Context) CXXDynamicCastExpr(Empty);
+      break;
+
+    case pch::EXPR_CXX_REINTERPRET_CAST:
+      S = new (Context) CXXReinterpretCastExpr(Empty);
+      break;
+
+    case pch::EXPR_CXX_CONST_CAST:
+      S = new (Context) CXXConstCastExpr(Empty);
+      break;
+
+    case pch::EXPR_CXX_FUNCTIONAL_CAST:
+      S = new (Context) CXXFunctionalCastExpr(Empty);
+      break;
+
+    case pch::EXPR_CXX_BOOL_LITERAL:
+      S = new (Context) CXXBoolLiteralExpr(Empty);
+      break;
+
+    case pch::EXPR_CXX_NULL_PTR_LITERAL:
+      S = new (Context) CXXNullPtrLiteralExpr(Empty);
+      break;
+    }
+
+    // We hit a STMT_STOP, so we're done with this expression.
+    if (Finished)
+      break;
+
+    ++NumStatementsRead;
+
+    if (S) {
+      unsigned NumSubStmts = Reader.Visit(S);
+      while (NumSubStmts > 0) {
+        StmtStack.pop_back();
+        --NumSubStmts;
+      }
+    }
+
+    assert(Idx == Record.size() && "Invalid deserialization of statement");
+    StmtStack.push_back(S);
+  }
+  assert(StmtStack.size() == 1 && "Extra expressions on stack!");
+  return StmtStack.back();
+}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
new file mode 100644
index 0000000..45d9b1b
--- /dev/null
+++ b/lib/Frontend/PCHWriter.cpp
@@ -0,0 +1,2324 @@
+//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- 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 PCHWriter class, which writes a precompiled header.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHWriter.h"
+#include "../Sema/Sema.h" // FIXME: move header into include/clang/Sema
+#include "../Sema/IdentifierResolver.h" // FIXME: move header
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Path.h"
+#include <cstdio>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Type serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class PCHTypeWriter {
+    PCHWriter &Writer;
+    PCHWriter::RecordData &Record;
+
+  public:
+    /// \brief Type code that corresponds to the record generated.
+    pch::TypeCode Code;
+
+    PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+      : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { }
+
+    void VisitArrayType(const ArrayType *T);
+    void VisitFunctionType(const FunctionType *T);
+    void VisitTagType(const TagType *T);
+
+#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+  };
+}
+
+void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
+  assert(false && "Built-in types are never serialized");
+}
+
+void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
+  Writer.AddTypeRef(T->getElementType(), Record);
+  Code = pch::TYPE_COMPLEX;
+}
+
+void PCHTypeWriter::VisitPointerType(const PointerType *T) {
+  Writer.AddTypeRef(T->getPointeeType(), Record);
+  Code = pch::TYPE_POINTER;
+}
+
+void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
+  Writer.AddTypeRef(T->getPointeeType(), Record);
+  Code = pch::TYPE_BLOCK_POINTER;
+}
+
+void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
+  Writer.AddTypeRef(T->getPointeeType(), Record);
+  Code = pch::TYPE_LVALUE_REFERENCE;
+}
+
+void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
+  Writer.AddTypeRef(T->getPointeeType(), Record);
+  Code = pch::TYPE_RVALUE_REFERENCE;
+}
+
+void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
+  Writer.AddTypeRef(T->getPointeeType(), Record);
+  Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
+  Code = pch::TYPE_MEMBER_POINTER;
+}
+
+void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
+  Writer.AddTypeRef(T->getElementType(), Record);
+  Record.push_back(T->getSizeModifier()); // FIXME: stable values
+  Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
+}
+
+void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
+  VisitArrayType(T);
+  Writer.AddAPInt(T->getSize(), Record);
+  Code = pch::TYPE_CONSTANT_ARRAY;
+}
+
+void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
+  VisitArrayType(T);
+  Code = pch::TYPE_INCOMPLETE_ARRAY;
+}
+
+void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
+  VisitArrayType(T);
+  Writer.AddSourceLocation(T->getLBracketLoc(), Record);
+  Writer.AddSourceLocation(T->getRBracketLoc(), Record);
+  Writer.AddStmt(T->getSizeExpr());
+  Code = pch::TYPE_VARIABLE_ARRAY;
+}
+
+void PCHTypeWriter::VisitVectorType(const VectorType *T) {
+  Writer.AddTypeRef(T->getElementType(), Record);
+  Record.push_back(T->getNumElements());
+  Record.push_back(T->isAltiVec());
+  Record.push_back(T->isPixel());
+  Code = pch::TYPE_VECTOR;
+}
+
+void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
+  VisitVectorType(T);
+  Code = pch::TYPE_EXT_VECTOR;
+}
+
+void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
+  Writer.AddTypeRef(T->getResultType(), Record);
+  Record.push_back(T->getNoReturnAttr());
+  // FIXME: need to stabilize encoding of calling convention...
+  Record.push_back(T->getCallConv());
+}
+
+void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
+  VisitFunctionType(T);
+  Code = pch::TYPE_FUNCTION_NO_PROTO;
+}
+
+void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
+  VisitFunctionType(T);
+  Record.push_back(T->getNumArgs());
+  for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
+    Writer.AddTypeRef(T->getArgType(I), Record);
+  Record.push_back(T->isVariadic());
+  Record.push_back(T->getTypeQuals());
+  Record.push_back(T->hasExceptionSpec());
+  Record.push_back(T->hasAnyExceptionSpec());
+  Record.push_back(T->getNumExceptions());
+  for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
+    Writer.AddTypeRef(T->getExceptionType(I), Record);
+  Code = pch::TYPE_FUNCTION_PROTO;
+}
+
+#if 0
+// For when we want it....
+void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+  Writer.AddDeclRef(T->getDecl(), Record);
+  Code = pch::TYPE_UNRESOLVED_USING;
+}
+#endif
+
+void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
+  Writer.AddDeclRef(T->getDecl(), Record);
+  Code = pch::TYPE_TYPEDEF;
+}
+
+void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
+  Writer.AddStmt(T->getUnderlyingExpr());
+  Code = pch::TYPE_TYPEOF_EXPR;
+}
+
+void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
+  Writer.AddTypeRef(T->getUnderlyingType(), Record);
+  Code = pch::TYPE_TYPEOF;
+}
+
+void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) {
+  Writer.AddStmt(T->getUnderlyingExpr());
+  Code = pch::TYPE_DECLTYPE;
+}
+
+void PCHTypeWriter::VisitTagType(const TagType *T) {
+  Writer.AddDeclRef(T->getDecl(), Record);
+  assert(!T->isBeingDefined() &&
+         "Cannot serialize in the middle of a type definition");
+}
+
+void PCHTypeWriter::VisitRecordType(const RecordType *T) {
+  VisitTagType(T);
+  Code = pch::TYPE_RECORD;
+}
+
+void PCHTypeWriter::VisitEnumType(const EnumType *T) {
+  VisitTagType(T);
+  Code = pch::TYPE_ENUM;
+}
+
+void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
+  Writer.AddTypeRef(T->getUnderlyingType(), Record);
+  Record.push_back(T->getTagKind());
+  Code = pch::TYPE_ELABORATED;
+}
+
+void
+PCHTypeWriter::VisitSubstTemplateTypeParmType(
+                                        const SubstTemplateTypeParmType *T) {
+  Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
+  Writer.AddTypeRef(T->getReplacementType(), Record);
+  Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
+}
+
+void
+PCHTypeWriter::VisitTemplateSpecializationType(
+                                       const TemplateSpecializationType *T) {
+  // FIXME: Serialize this type (C++ only)
+  assert(false && "Cannot serialize template specialization types");
+}
+
+void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) {
+  // FIXME: Serialize this type (C++ only)
+  assert(false && "Cannot serialize qualified name types");
+}
+
+void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+  Writer.AddDeclRef(T->getDecl(), Record);
+  Record.push_back(T->getNumProtocols());
+  for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
+       E = T->qual_end(); I != E; ++I)
+    Writer.AddDeclRef(*I, Record);
+  Code = pch::TYPE_OBJC_INTERFACE;
+}
+
+void
+PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+  Writer.AddTypeRef(T->getPointeeType(), Record);
+  Record.push_back(T->getNumProtocols());
+  for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
+       E = T->qual_end(); I != E; ++I)
+    Writer.AddDeclRef(*I, Record);
+  Code = pch::TYPE_OBJC_OBJECT_POINTER;
+}
+
+namespace {
+
+class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
+  PCHWriter &Writer;
+  PCHWriter::RecordData &Record;
+
+public:
+  TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+    : Writer(Writer), Record(Record) { }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+    void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+  void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
+  void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
+};
+
+}
+
+void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+  // nothing to do
+}
+void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getBuiltinLoc(), Record);
+  if (TL.needsExtraLocalData()) {
+    Record.push_back(TL.getWrittenTypeSpec());
+    Record.push_back(TL.getWrittenSignSpec());
+    Record.push_back(TL.getWrittenWidthSpec());
+    Record.push_back(TL.hasModeAttr());
+  }
+}
+void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getCaretLoc(), Record);
+}
+void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getAmpLoc(), Record);
+}
+void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record);
+}
+void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getLBracketLoc(), Record);
+  Writer.AddSourceLocation(TL.getRBracketLoc(), Record);
+  Record.push_back(TL.getSizeExpr() ? 1 : 0);
+  if (TL.getSizeExpr())
+    Writer.AddStmt(TL.getSizeExpr());
+}
+void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
+                                            DependentSizedArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
+                                        DependentSizedExtVectorTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    Writer.AddDeclRef(TL.getArg(i), Record);
+}
+void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+  VisitFunctionTypeLoc(TL);
+}
+void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+  VisitFunctionTypeLoc(TL);
+}
+void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
+  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+}
+void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
+  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+  Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record);
+}
+void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
+                                            SubstTemplateTypeParmTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
+                                           TemplateSpecializationTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record);
+  Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+  Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    Writer.AddTemplateArgumentLoc(TL.getArgLoc(i), Record);
+}
+void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+  Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+  Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+    Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
+}
+void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getStarLoc(), Record);
+  Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+  Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+  Record.push_back(TL.hasBaseTypeAsWritten());
+  Record.push_back(TL.hasProtocolsAsWritten());
+  if (TL.hasProtocolsAsWritten())
+    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+      Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
+}
+
+//===----------------------------------------------------------------------===//
+// PCHWriter Implementation
+//===----------------------------------------------------------------------===//
+
+static void EmitBlockID(unsigned ID, const char *Name,
+                        llvm::BitstreamWriter &Stream,
+                        PCHWriter::RecordData &Record) {
+  Record.clear();
+  Record.push_back(ID);
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
+
+  // Emit the block name if present.
+  if (Name == 0 || Name[0] == 0) return;
+  Record.clear();
+  while (*Name)
+    Record.push_back(*Name++);
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
+}
+
+static void EmitRecordID(unsigned ID, const char *Name,
+                         llvm::BitstreamWriter &Stream,
+                         PCHWriter::RecordData &Record) {
+  Record.clear();
+  Record.push_back(ID);
+  while (*Name)
+    Record.push_back(*Name++);
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
+}
+
+static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
+                          PCHWriter::RecordData &Record) {
+#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
+  RECORD(STMT_STOP);
+  RECORD(STMT_NULL_PTR);
+  RECORD(STMT_NULL);
+  RECORD(STMT_COMPOUND);
+  RECORD(STMT_CASE);
+  RECORD(STMT_DEFAULT);
+  RECORD(STMT_LABEL);
+  RECORD(STMT_IF);
+  RECORD(STMT_SWITCH);
+  RECORD(STMT_WHILE);
+  RECORD(STMT_DO);
+  RECORD(STMT_FOR);
+  RECORD(STMT_GOTO);
+  RECORD(STMT_INDIRECT_GOTO);
+  RECORD(STMT_CONTINUE);
+  RECORD(STMT_BREAK);
+  RECORD(STMT_RETURN);
+  RECORD(STMT_DECL);
+  RECORD(STMT_ASM);
+  RECORD(EXPR_PREDEFINED);
+  RECORD(EXPR_DECL_REF);
+  RECORD(EXPR_INTEGER_LITERAL);
+  RECORD(EXPR_FLOATING_LITERAL);
+  RECORD(EXPR_IMAGINARY_LITERAL);
+  RECORD(EXPR_STRING_LITERAL);
+  RECORD(EXPR_CHARACTER_LITERAL);
+  RECORD(EXPR_PAREN);
+  RECORD(EXPR_UNARY_OPERATOR);
+  RECORD(EXPR_SIZEOF_ALIGN_OF);
+  RECORD(EXPR_ARRAY_SUBSCRIPT);
+  RECORD(EXPR_CALL);
+  RECORD(EXPR_MEMBER);
+  RECORD(EXPR_BINARY_OPERATOR);
+  RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);
+  RECORD(EXPR_CONDITIONAL_OPERATOR);
+  RECORD(EXPR_IMPLICIT_CAST);
+  RECORD(EXPR_CSTYLE_CAST);
+  RECORD(EXPR_COMPOUND_LITERAL);
+  RECORD(EXPR_EXT_VECTOR_ELEMENT);
+  RECORD(EXPR_INIT_LIST);
+  RECORD(EXPR_DESIGNATED_INIT);
+  RECORD(EXPR_IMPLICIT_VALUE_INIT);
+  RECORD(EXPR_VA_ARG);
+  RECORD(EXPR_ADDR_LABEL);
+  RECORD(EXPR_STMT);
+  RECORD(EXPR_TYPES_COMPATIBLE);
+  RECORD(EXPR_CHOOSE);
+  RECORD(EXPR_GNU_NULL);
+  RECORD(EXPR_SHUFFLE_VECTOR);
+  RECORD(EXPR_BLOCK);
+  RECORD(EXPR_BLOCK_DECL_REF);
+  RECORD(EXPR_OBJC_STRING_LITERAL);
+  RECORD(EXPR_OBJC_ENCODE);
+  RECORD(EXPR_OBJC_SELECTOR_EXPR);
+  RECORD(EXPR_OBJC_PROTOCOL_EXPR);
+  RECORD(EXPR_OBJC_IVAR_REF_EXPR);
+  RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);
+  RECORD(EXPR_OBJC_KVC_REF_EXPR);
+  RECORD(EXPR_OBJC_MESSAGE_EXPR);
+  RECORD(EXPR_OBJC_SUPER_EXPR);
+  RECORD(STMT_OBJC_FOR_COLLECTION);
+  RECORD(STMT_OBJC_CATCH);
+  RECORD(STMT_OBJC_FINALLY);
+  RECORD(STMT_OBJC_AT_TRY);
+  RECORD(STMT_OBJC_AT_SYNCHRONIZED);
+  RECORD(STMT_OBJC_AT_THROW);
+  RECORD(EXPR_CXX_OPERATOR_CALL);
+  RECORD(EXPR_CXX_CONSTRUCT);
+  RECORD(EXPR_CXX_STATIC_CAST);
+  RECORD(EXPR_CXX_DYNAMIC_CAST);
+  RECORD(EXPR_CXX_REINTERPRET_CAST);
+  RECORD(EXPR_CXX_CONST_CAST);
+  RECORD(EXPR_CXX_FUNCTIONAL_CAST);
+  RECORD(EXPR_CXX_BOOL_LITERAL);
+  RECORD(EXPR_CXX_NULL_PTR_LITERAL);
+#undef RECORD
+}
+
+void PCHWriter::WriteBlockInfoBlock() {
+  RecordData Record;
+  Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
+
+#define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record)
+#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
+
+  // PCH Top-Level Block.
+  BLOCK(PCH_BLOCK);
+  RECORD(ORIGINAL_FILE_NAME);
+  RECORD(TYPE_OFFSET);
+  RECORD(DECL_OFFSET);
+  RECORD(LANGUAGE_OPTIONS);
+  RECORD(METADATA);
+  RECORD(IDENTIFIER_OFFSET);
+  RECORD(IDENTIFIER_TABLE);
+  RECORD(EXTERNAL_DEFINITIONS);
+  RECORD(SPECIAL_TYPES);
+  RECORD(STATISTICS);
+  RECORD(TENTATIVE_DEFINITIONS);
+  RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS);
+  RECORD(SELECTOR_OFFSETS);
+  RECORD(METHOD_POOL);
+  RECORD(PP_COUNTER_VALUE);
+  RECORD(SOURCE_LOCATION_OFFSETS);
+  RECORD(SOURCE_LOCATION_PRELOADS);
+  RECORD(STAT_CACHE);
+  RECORD(EXT_VECTOR_DECLS);
+  RECORD(COMMENT_RANGES);
+  RECORD(VERSION_CONTROL_BRANCH_REVISION);
+  
+  // SourceManager Block.
+  BLOCK(SOURCE_MANAGER_BLOCK);
+  RECORD(SM_SLOC_FILE_ENTRY);
+  RECORD(SM_SLOC_BUFFER_ENTRY);
+  RECORD(SM_SLOC_BUFFER_BLOB);
+  RECORD(SM_SLOC_INSTANTIATION_ENTRY);
+  RECORD(SM_LINE_TABLE);
+  RECORD(SM_HEADER_FILE_INFO);
+
+  // Preprocessor Block.
+  BLOCK(PREPROCESSOR_BLOCK);
+  RECORD(PP_MACRO_OBJECT_LIKE);
+  RECORD(PP_MACRO_FUNCTION_LIKE);
+  RECORD(PP_TOKEN);
+
+  // Decls and Types block.
+  BLOCK(DECLTYPES_BLOCK);
+  RECORD(TYPE_EXT_QUAL);
+  RECORD(TYPE_COMPLEX);
+  RECORD(TYPE_POINTER);
+  RECORD(TYPE_BLOCK_POINTER);
+  RECORD(TYPE_LVALUE_REFERENCE);
+  RECORD(TYPE_RVALUE_REFERENCE);
+  RECORD(TYPE_MEMBER_POINTER);
+  RECORD(TYPE_CONSTANT_ARRAY);
+  RECORD(TYPE_INCOMPLETE_ARRAY);
+  RECORD(TYPE_VARIABLE_ARRAY);
+  RECORD(TYPE_VECTOR);
+  RECORD(TYPE_EXT_VECTOR);
+  RECORD(TYPE_FUNCTION_PROTO);
+  RECORD(TYPE_FUNCTION_NO_PROTO);
+  RECORD(TYPE_TYPEDEF);
+  RECORD(TYPE_TYPEOF_EXPR);
+  RECORD(TYPE_TYPEOF);
+  RECORD(TYPE_RECORD);
+  RECORD(TYPE_ENUM);
+  RECORD(TYPE_OBJC_INTERFACE);
+  RECORD(TYPE_OBJC_OBJECT_POINTER);
+  RECORD(DECL_ATTR);
+  RECORD(DECL_TRANSLATION_UNIT);
+  RECORD(DECL_TYPEDEF);
+  RECORD(DECL_ENUM);
+  RECORD(DECL_RECORD);
+  RECORD(DECL_ENUM_CONSTANT);
+  RECORD(DECL_FUNCTION);
+  RECORD(DECL_OBJC_METHOD);
+  RECORD(DECL_OBJC_INTERFACE);
+  RECORD(DECL_OBJC_PROTOCOL);
+  RECORD(DECL_OBJC_IVAR);
+  RECORD(DECL_OBJC_AT_DEFS_FIELD);
+  RECORD(DECL_OBJC_CLASS);
+  RECORD(DECL_OBJC_FORWARD_PROTOCOL);
+  RECORD(DECL_OBJC_CATEGORY);
+  RECORD(DECL_OBJC_CATEGORY_IMPL);
+  RECORD(DECL_OBJC_IMPLEMENTATION);
+  RECORD(DECL_OBJC_COMPATIBLE_ALIAS);
+  RECORD(DECL_OBJC_PROPERTY);
+  RECORD(DECL_OBJC_PROPERTY_IMPL);
+  RECORD(DECL_FIELD);
+  RECORD(DECL_VAR);
+  RECORD(DECL_IMPLICIT_PARAM);
+  RECORD(DECL_PARM_VAR);
+  RECORD(DECL_FILE_SCOPE_ASM);
+  RECORD(DECL_BLOCK);
+  RECORD(DECL_CONTEXT_LEXICAL);
+  RECORD(DECL_CONTEXT_VISIBLE);
+  // Statements and Exprs can occur in the Decls and Types block.
+  AddStmtsExprs(Stream, Record);
+#undef RECORD
+#undef BLOCK
+  Stream.ExitBlock();
+}
+
+/// \brief Adjusts the given filename to only write out the portion of the
+/// filename that is not part of the system root directory.
+///
+/// \param Filename the file name to adjust.
+///
+/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and
+/// the returned filename will be adjusted by this system root.
+///
+/// \returns either the original filename (if it needs no adjustment) or the
+/// adjusted filename (which points into the @p Filename parameter).
+static const char *
+adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) {
+  assert(Filename && "No file name to adjust?");
+
+  if (!isysroot)
+    return Filename;
+
+  // Verify that the filename and the system root have the same prefix.
+  unsigned Pos = 0;
+  for (; Filename[Pos] && isysroot[Pos]; ++Pos)
+    if (Filename[Pos] != isysroot[Pos])
+      return Filename; // Prefixes don't match.
+
+  // We hit the end of the filename before we hit the end of the system root.
+  if (!Filename[Pos])
+    return Filename;
+
+  // If the file name has a '/' at the current position, skip over the '/'.
+  // We distinguish sysroot-based includes from absolute includes by the
+  // absence of '/' at the beginning of sysroot-based includes.
+  if (Filename[Pos] == '/')
+    ++Pos;
+
+  return Filename + Pos;
+}
+
+/// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
+void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
+  using namespace llvm;
+
+  // Metadata
+  const TargetInfo &Target = Context.Target;
+  BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
+  MetaAbbrev->Add(BitCodeAbbrevOp(pch::METADATA));
+  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major
+  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH 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::Blob)); // Target triple
+  unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
+
+  RecordData Record;
+  Record.push_back(pch::METADATA);
+  Record.push_back(pch::VERSION_MAJOR);
+  Record.push_back(pch::VERSION_MINOR);
+  Record.push_back(CLANG_VERSION_MAJOR);
+  Record.push_back(CLANG_VERSION_MINOR);
+  Record.push_back(isysroot != 0);
+  const std::string &TripleStr = Target.getTriple().getTriple();
+  Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, TripleStr);
+
+  // Original file name
+  SourceManager &SM = Context.getSourceManager();
+  if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+    BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
+    FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME));
+    FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+    unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
+
+    llvm::sys::Path MainFilePath(MainFile->getName());
+    std::string MainFileName;
+
+    if (!MainFilePath.isAbsolute()) {
+      llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
+      P.appendComponent(MainFilePath.str());
+      MainFileName = P.str();
+    } else {
+      MainFileName = MainFilePath.str();
+    }
+
+    const char *MainFileNameStr = MainFileName.c_str();
+    MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
+                                                      isysroot);
+    RecordData Record;
+    Record.push_back(pch::ORIGINAL_FILE_NAME);
+    Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
+  }
+  
+  // Repository branch/version information.
+  BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
+  RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
+  RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
+  unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
+  Record.clear();
+  Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION);
+  Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
+                            getClangFullRepositoryVersion());
+}
+
+/// \brief Write the LangOptions structure.
+void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
+  RecordData Record;
+  Record.push_back(LangOpts.Trigraphs);
+  Record.push_back(LangOpts.BCPLComment);  // BCPL-style '//' comments.
+  Record.push_back(LangOpts.DollarIdents);  // '$' allowed in identifiers.
+  Record.push_back(LangOpts.AsmPreprocessor);  // Preprocessor in asm mode.
+  Record.push_back(LangOpts.GNUMode);  // True in gnu99 mode false in c99 mode (etc)
+  Record.push_back(LangOpts.ImplicitInt);  // C89 implicit 'int'.
+  Record.push_back(LangOpts.Digraphs);  // C94, C99 and C++
+  Record.push_back(LangOpts.HexFloats);  // C99 Hexadecimal float constants.
+  Record.push_back(LangOpts.C99);  // C99 Support
+  Record.push_back(LangOpts.Microsoft);  // Microsoft extensions.
+  Record.push_back(LangOpts.CPlusPlus);  // C++ Support
+  Record.push_back(LangOpts.CPlusPlus0x);  // C++0x Support
+  Record.push_back(LangOpts.CXXOperatorNames);  // Treat C++ operator names as keywords.
+
+  Record.push_back(LangOpts.ObjC1);  // Objective-C 1 support enabled.
+  Record.push_back(LangOpts.ObjC2);  // Objective-C 2 support enabled.
+  Record.push_back(LangOpts.ObjCNonFragileABI);  // Objective-C 
+                                                 // modern abi enabled.
+  Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced 
+                                                 // modern abi enabled.
+
+  Record.push_back(LangOpts.PascalStrings);  // Allow Pascal strings
+  Record.push_back(LangOpts.WritableStrings);  // Allow writable strings
+  Record.push_back(LangOpts.LaxVectorConversions);
+  Record.push_back(LangOpts.AltiVec);
+  Record.push_back(LangOpts.Exceptions);  // Support exception handling.
+
+  Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
+  Record.push_back(LangOpts.Freestanding); // Freestanding implementation
+  Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin)
+
+  // Whether static initializers are protected by locks.
+  Record.push_back(LangOpts.ThreadsafeStatics);
+  Record.push_back(LangOpts.POSIXThreads);
+  Record.push_back(LangOpts.Blocks); // block extension to C
+  Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if
+                                  // they are unused.
+  Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
+                                  // (modulo the platform support).
+
+  Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when
+                                  // signed integer arithmetic overflows.
+
+  Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and
+                                  // may be ripped out at any time.
+
+  Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
+  Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
+                                  // defined.
+  Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as
+                                  // opposed to __DYNAMIC__).
+  Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero.
+
+  Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be
+                                  // used (instead of C99 semantics).
+  Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined.
+  Record.push_back(LangOpts.AccessControl); // Whether C++ access control should
+                                            // be enabled.
+  Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
+                                           // unsigned type
+  Record.push_back(LangOpts.ShortWChar);  // force wchar_t to be unsigned short
+  Record.push_back(LangOpts.getGCMode());
+  Record.push_back(LangOpts.getVisibilityMode());
+  Record.push_back(LangOpts.getStackProtectorMode());
+  Record.push_back(LangOpts.InstantiationDepth);
+  Record.push_back(LangOpts.OpenCL);
+  Record.push_back(LangOpts.CatchUndefined);
+  Record.push_back(LangOpts.ElideConstructors);
+  Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
+}
+
+//===----------------------------------------------------------------------===//
+// stat cache Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+// Trait used for the on-disk hash table of stat cache results.
+class PCHStatCacheTrait {
+public:
+  typedef const char * key_type;
+  typedef key_type key_type_ref;
+
+  typedef std::pair<int, struct stat> data_type;
+  typedef const data_type& data_type_ref;
+
+  static unsigned ComputeHash(const char *path) {
+    return llvm::HashString(path);
+  }
+
+  std::pair<unsigned,unsigned>
+    EmitKeyDataLength(llvm::raw_ostream& Out, const char *path,
+                      data_type_ref Data) {
+    unsigned StrLen = strlen(path);
+    clang::io::Emit16(Out, StrLen);
+    unsigned DataLen = 1; // result value
+    if (Data.first == 0)
+      DataLen += 4 + 4 + 2 + 8 + 8;
+    clang::io::Emit8(Out, DataLen);
+    return std::make_pair(StrLen + 1, DataLen);
+  }
+
+  void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) {
+    Out.write(path, KeyLen);
+  }
+
+  void EmitData(llvm::raw_ostream& Out, key_type_ref,
+                data_type_ref Data, unsigned DataLen) {
+    using namespace clang::io;
+    uint64_t Start = Out.tell(); (void)Start;
+
+    // Result of stat()
+    Emit8(Out, Data.first? 1 : 0);
+
+    if (Data.first == 0) {
+      Emit32(Out, (uint32_t) Data.second.st_ino);
+      Emit32(Out, (uint32_t) Data.second.st_dev);
+      Emit16(Out, (uint16_t) Data.second.st_mode);
+      Emit64(Out, (uint64_t) Data.second.st_mtime);
+      Emit64(Out, (uint64_t) Data.second.st_size);
+    }
+
+    assert(Out.tell() - Start == DataLen && "Wrong data length");
+  }
+};
+} // end anonymous namespace
+
+/// \brief Write the stat() system call cache to the PCH file.
+void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls,
+                               const char *isysroot) {
+  // Build the on-disk hash table containing information about every
+  // stat() call.
+  OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator;
+  unsigned NumStatEntries = 0;
+  for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
+                                StatEnd = StatCalls.end();
+       Stat != StatEnd; ++Stat, ++NumStatEntries) {
+    const char *Filename = Stat->first();
+    Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+    Generator.insert(Filename, Stat->second);
+  }
+
+  // Create the on-disk hash table in a buffer.
+  llvm::SmallString<4096> StatCacheData;
+  uint32_t BucketOffset;
+  {
+    llvm::raw_svector_ostream Out(StatCacheData);
+    // Make sure that no bucket is at offset 0
+    clang::io::Emit32(Out, 0);
+    BucketOffset = Generator.Emit(Out);
+  }
+
+  // Create a blob abbreviation
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::STAT_CACHE));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+  unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev);
+
+  // Write the stat cache
+  RecordData Record;
+  Record.push_back(pch::STAT_CACHE);
+  Record.push_back(BucketOffset);
+  Record.push_back(NumStatEntries);
+  Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str());
+}
+
+//===----------------------------------------------------------------------===//
+// Source Manager Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// file.
+static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+  return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer.
+static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
+  return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer's blob.
+static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
+  return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to an
+/// buffer.
+static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
+  return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Writes the block containing the serialized form of the
+/// source manager.
+///
+/// TODO: We should probably use an on-disk hash table (stored in a
+/// blob), indexed based on the file name, so that we only create
+/// entries for files that we actually need. In the common case (no
+/// errors), we probably won't have to create file entries for any of
+/// the files in the AST.
+void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
+                                        const Preprocessor &PP,
+                                        const char *isysroot) {
+  RecordData Record;
+
+  // Enter the source manager block.
+  Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
+
+  // Abbreviations for the various kinds of source-location entries.
+  unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
+  unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);
+  unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream);
+  unsigned SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream);
+
+  // Write the line table.
+  if (SourceMgr.hasLineTable()) {
+    LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+    // Emit the file names
+    Record.push_back(LineTable.getNumFilenames());
+    for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
+      // Emit the file name
+      const char *Filename = LineTable.getFilename(I);
+      Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+      unsigned FilenameLen = Filename? strlen(Filename) : 0;
+      Record.push_back(FilenameLen);
+      if (FilenameLen)
+        Record.insert(Record.end(), Filename, Filename + FilenameLen);
+    }
+
+    // Emit the line entries
+    for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
+         L != LEnd; ++L) {
+      // Emit the file ID
+      Record.push_back(L->first);
+
+      // Emit the line entries
+      Record.push_back(L->second.size());
+      for (std::vector<LineEntry>::iterator LE = L->second.begin(),
+                                         LEEnd = L->second.end();
+           LE != LEEnd; ++LE) {
+        Record.push_back(LE->FileOffset);
+        Record.push_back(LE->LineNo);
+        Record.push_back(LE->FilenameID);
+        Record.push_back((unsigned)LE->FileKind);
+        Record.push_back(LE->IncludeOffset);
+      }
+    }
+    Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
+  }
+
+  // Write out entries for all of the header files we know about.
+  HeaderSearch &HS = PP.getHeaderSearchInfo();
+  Record.clear();
+  for (HeaderSearch::header_file_iterator I = HS.header_file_begin(),
+                                          E = HS.header_file_end();
+       I != E; ++I) {
+    Record.push_back(I->isImport);
+    Record.push_back(I->DirInfo);
+    Record.push_back(I->NumIncludes);
+    AddIdentifierRef(I->ControllingMacro, Record);
+    Stream.EmitRecord(pch::SM_HEADER_FILE_INFO, Record);
+    Record.clear();
+  }
+
+  // Write out the source location entry table. We skip the first
+  // entry, which is always the same dummy entry.
+  std::vector<uint32_t> SLocEntryOffsets;
+  RecordData PreloadSLocs;
+  SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1);
+  for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) {
+    // Get this source location entry.
+    const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
+    
+    // Record the offset of this source-location entry.
+    SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
+
+    // Figure out which record code to use.
+    unsigned Code;
+    if (SLoc->isFile()) {
+      if (SLoc->getFile().getContentCache()->Entry)
+        Code = pch::SM_SLOC_FILE_ENTRY;
+      else
+        Code = pch::SM_SLOC_BUFFER_ENTRY;
+    } else
+      Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
+    Record.clear();
+    Record.push_back(Code);
+
+    Record.push_back(SLoc->getOffset());
+    if (SLoc->isFile()) {
+      const SrcMgr::FileInfo &File = SLoc->getFile();
+      Record.push_back(File.getIncludeLoc().getRawEncoding());
+      Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
+      Record.push_back(File.hasLineDirectives());
+
+      const SrcMgr::ContentCache *Content = File.getContentCache();
+      if (Content->Entry) {
+        // The source location entry is a file. The blob associated
+        // with this entry is the file name.
+
+        // Turn the file name into an absolute path, if it isn't already.
+        const char *Filename = Content->Entry->getName();
+        llvm::sys::Path FilePath(Filename, strlen(Filename));
+        std::string FilenameStr;
+        if (!FilePath.isAbsolute()) {
+          llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
+          P.appendComponent(FilePath.str());
+          FilenameStr = P.str();
+          Filename = FilenameStr.c_str();
+        }
+
+        Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+        Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename);
+
+        // FIXME: For now, preload all file source locations, so that
+        // we get the appropriate File entries in the reader. This is
+        // a temporary measure.
+        PreloadSLocs.push_back(SLocEntryOffsets.size());
+      } else {
+        // The source location entry is a buffer. The blob associated
+        // with this entry contains the contents of the buffer.
+
+        // We add one to the size so that we capture the trailing NULL
+        // that is required by llvm::MemoryBuffer::getMemBuffer (on
+        // the reader side).
+        const llvm::MemoryBuffer *Buffer = Content->getBuffer();
+        const char *Name = Buffer->getBufferIdentifier();
+        Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
+                                  llvm::StringRef(Name, strlen(Name) + 1));
+        Record.clear();
+        Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
+        Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
+                                  llvm::StringRef(Buffer->getBufferStart(),
+                                                  Buffer->getBufferSize() + 1));
+
+        if (strcmp(Name, "<built-in>") == 0)
+          PreloadSLocs.push_back(SLocEntryOffsets.size());
+      }
+    } else {
+      // The source location entry is an instantiation.
+      const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
+      Record.push_back(Inst.getSpellingLoc().getRawEncoding());
+      Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
+      Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
+
+      // Compute the token length for this macro expansion.
+      unsigned NextOffset = SourceMgr.getNextOffset();
+      if (I + 1 != N)
+        NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
+      Record.push_back(NextOffset - SLoc->getOffset() - 1);
+      Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
+    }
+  }
+
+  Stream.ExitBlock();
+
+  if (SLocEntryOffsets.empty())
+    return;
+
+  // Write the source-location offsets table into the PCH block. This
+  // table is used for lazily loading source-location information.
+  using namespace llvm;
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
+  unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
+
+  Record.clear();
+  Record.push_back(pch::SOURCE_LOCATION_OFFSETS);
+  Record.push_back(SLocEntryOffsets.size());
+  Record.push_back(SourceMgr.getNextOffset());
+  Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
+                            (const char *)&SLocEntryOffsets.front(),
+                           SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0]));
+
+  // Write the source location entry preloads array, telling the PCH
+  // reader which source locations entries it should load eagerly.
+  Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs);
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Writes the block containing the serialized form of the
+/// preprocessor.
+///
+void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
+  RecordData Record;
+
+  // If the preprocessor __COUNTER__ value has been bumped, remember it.
+  if (PP.getCounterValue() != 0) {
+    Record.push_back(PP.getCounterValue());
+    Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record);
+    Record.clear();
+  }
+
+  // Enter the preprocessor block.
+  Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2);
+
+  // If the PCH file contains __DATE__ or __TIME__ emit a warning about this.
+  // FIXME: use diagnostics subsystem for localization etc.
+  if (PP.SawDateOrTime())
+    fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
+
+  // Loop over all the macro definitions that are live at the end of the file,
+  // emitting each to the PP section.
+  for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
+       I != E; ++I) {
+    // FIXME: This emits macros in hash table order, we should do it in a stable
+    // order so that output is reproducible.
+    MacroInfo *MI = I->second;
+
+    // Don't emit builtin macros like __LINE__ to the PCH file unless they have
+    // been redefined by the header (in which case they are not isBuiltinMacro).
+    if (MI->isBuiltinMacro())
+      continue;
+
+    AddIdentifierRef(I->first, Record);
+    MacroOffsets[I->first] = Stream.GetCurrentBitNo();
+    Record.push_back(MI->getDefinitionLoc().getRawEncoding());
+    Record.push_back(MI->isUsed());
+
+    unsigned Code;
+    if (MI->isObjectLike()) {
+      Code = pch::PP_MACRO_OBJECT_LIKE;
+    } else {
+      Code = pch::PP_MACRO_FUNCTION_LIKE;
+
+      Record.push_back(MI->isC99Varargs());
+      Record.push_back(MI->isGNUVarargs());
+      Record.push_back(MI->getNumArgs());
+      for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
+           I != E; ++I)
+        AddIdentifierRef(*I, Record);
+    }
+    Stream.EmitRecord(Code, Record);
+    Record.clear();
+
+    // Emit the tokens array.
+    for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
+      // Note that we know that the preprocessor does not have any annotation
+      // tokens in it because they are created by the parser, and thus can't be
+      // in a macro definition.
+      const Token &Tok = MI->getReplacementToken(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(pch::PP_TOKEN, Record);
+      Record.clear();
+    }
+    ++NumMacros;
+  }
+  Stream.ExitBlock();
+}
+
+void PCHWriter::WriteComments(ASTContext &Context) {
+  using namespace llvm;
+
+  if (Context.Comments.empty())
+    return;
+
+  BitCodeAbbrev *CommentAbbrev = new BitCodeAbbrev();
+  CommentAbbrev->Add(BitCodeAbbrevOp(pch::COMMENT_RANGES));
+  CommentAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+  unsigned CommentCode = Stream.EmitAbbrev(CommentAbbrev);
+
+  RecordData Record;
+  Record.push_back(pch::COMMENT_RANGES);
+  Stream.EmitRecordWithBlob(CommentCode, Record,
+                            (const char*)&Context.Comments[0],
+                            Context.Comments.size() * sizeof(SourceRange));
+}
+
+//===----------------------------------------------------------------------===//
+// Type Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Write the representation of a type to the PCH stream.
+void PCHWriter::WriteType(QualType T) {
+  pch::TypeID &ID = TypeIDs[T];
+  if (ID == 0) // we haven't seen this type before.
+    ID = NextTypeID++;
+
+  // Record the offset for this type.
+  if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
+    TypeOffsets.push_back(Stream.GetCurrentBitNo());
+  else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
+    TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
+    TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = Stream.GetCurrentBitNo();
+  }
+
+  RecordData Record;
+
+  // Emit the type's representation.
+  PCHTypeWriter W(*this, Record);
+
+  if (T.hasLocalNonFastQualifiers()) {
+    Qualifiers Qs = T.getLocalQualifiers();
+    AddTypeRef(T.getLocalUnqualifiedType(), Record);
+    Record.push_back(Qs.getAsOpaqueValue());
+    W.Code = pch::TYPE_EXT_QUAL;
+  } else {
+    switch (T->getTypeClass()) {
+      // For all of the concrete, non-dependent types, call the
+      // appropriate visitor function.
+#define TYPE(Class, Base) \
+    case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+
+      // For all of the dependent type nodes (which only occur in C++
+      // templates), produce an error.
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+      assert(false && "Cannot serialize dependent type nodes");
+      break;
+    }
+  }
+
+  // Emit the serialized record.
+  Stream.EmitRecord(W.Code, Record);
+
+  // Flush any expressions that were written as part of this type.
+  FlushStmts();
+}
+
+//===----------------------------------------------------------------------===//
+// Declaration Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Write the block containing all of the declaration IDs
+/// lexically declared within the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
+/// bistream, or 0 if no block was written.
+uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
+                                                 DeclContext *DC) {
+  if (DC->decls_empty())
+    return 0;
+
+  uint64_t Offset = Stream.GetCurrentBitNo();
+  RecordData Record;
+  for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
+         D != DEnd; ++D)
+    AddDeclRef(*D, Record);
+
+  ++NumLexicalDeclContexts;
+  Stream.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
+  return Offset;
+}
+
+/// \brief Write the block containing all of the declaration IDs
+/// visible from the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
+/// bistream, or 0 if no block was written.
+uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
+                                                 DeclContext *DC) {
+  if (DC->getPrimaryContext() != DC)
+    return 0;
+
+  // Since there is no name lookup into functions or methods, and we
+  // perform name lookup for the translation unit via the
+  // IdentifierInfo chains, don't bother to build a
+  // visible-declarations table for these entities.
+  if (DC->isFunctionOrMethod() || DC->isTranslationUnit())
+    return 0;
+
+  // Force the DeclContext to build a its name-lookup table.
+  DC->lookup(DeclarationName());
+
+  // Serialize the contents of the mapping used for lookup. Note that,
+  // although we have two very different code paths, the serialized
+  // representation is the same for both cases: a declaration name,
+  // followed by a size, followed by references to the visible
+  // declarations that have that name.
+  uint64_t Offset = Stream.GetCurrentBitNo();
+  RecordData Record;
+  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+  if (!Map)
+    return 0;
+
+  for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+       D != DEnd; ++D) {
+    AddDeclarationName(D->first, Record);
+    DeclContext::lookup_result Result = D->second.getLookupResult(Context);
+    Record.push_back(Result.second - Result.first);
+    for (; Result.first != Result.second; ++Result.first)
+      AddDeclRef(*Result.first, Record);
+  }
+
+  if (Record.size() == 0)
+    return 0;
+
+  Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
+  ++NumVisibleDeclContexts;
+  return Offset;
+}
+
+//===----------------------------------------------------------------------===//
+// Global Method Pool and Selector Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+// Trait used for the on-disk hash table used in the method pool.
+class PCHMethodPoolTrait {
+  PCHWriter &Writer;
+
+public:
+  typedef Selector key_type;
+  typedef key_type key_type_ref;
+
+  typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
+  typedef const data_type& data_type_ref;
+
+  explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { }
+
+  static unsigned ComputeHash(Selector Sel) {
+    unsigned N = Sel.getNumArgs();
+    if (N == 0)
+      ++N;
+    unsigned R = 5381;
+    for (unsigned I = 0; I != N; ++I)
+      if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
+        R = llvm::HashString(II->getName(), R);
+    return R;
+  }
+
+  std::pair<unsigned,unsigned>
+    EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel,
+                      data_type_ref Methods) {
+    unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
+    clang::io::Emit16(Out, KeyLen);
+    unsigned DataLen = 2 + 2; // 2 bytes for each of the method counts
+    for (const ObjCMethodList *Method = &Methods.first; Method;
+         Method = Method->Next)
+      if (Method->Method)
+        DataLen += 4;
+    for (const ObjCMethodList *Method = &Methods.second; Method;
+         Method = Method->Next)
+      if (Method->Method)
+        DataLen += 4;
+    clang::io::Emit16(Out, DataLen);
+    return std::make_pair(KeyLen, DataLen);
+  }
+
+  void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) {
+    uint64_t Start = Out.tell();
+    assert((Start >> 32) == 0 && "Selector key offset too large");
+    Writer.SetSelectorOffset(Sel, Start);
+    unsigned N = Sel.getNumArgs();
+    clang::io::Emit16(Out, N);
+    if (N == 0)
+      N = 1;
+    for (unsigned I = 0; I != N; ++I)
+      clang::io::Emit32(Out,
+                    Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
+  }
+
+  void EmitData(llvm::raw_ostream& Out, key_type_ref,
+                data_type_ref Methods, unsigned DataLen) {
+    uint64_t Start = Out.tell(); (void)Start;
+    unsigned NumInstanceMethods = 0;
+    for (const ObjCMethodList *Method = &Methods.first; Method;
+         Method = Method->Next)
+      if (Method->Method)
+        ++NumInstanceMethods;
+
+    unsigned NumFactoryMethods = 0;
+    for (const ObjCMethodList *Method = &Methods.second; Method;
+         Method = Method->Next)
+      if (Method->Method)
+        ++NumFactoryMethods;
+
+    clang::io::Emit16(Out, NumInstanceMethods);
+    clang::io::Emit16(Out, NumFactoryMethods);
+    for (const ObjCMethodList *Method = &Methods.first; Method;
+         Method = Method->Next)
+      if (Method->Method)
+        clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+    for (const ObjCMethodList *Method = &Methods.second; Method;
+         Method = Method->Next)
+      if (Method->Method)
+        clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+
+    assert(Out.tell() - Start == DataLen && "Data length is wrong");
+  }
+};
+} // end anonymous namespace
+
+/// \brief Write the method pool into the PCH file.
+///
+/// The method pool contains both instance and factory methods, stored
+/// in an on-disk hash table indexed by the selector.
+void PCHWriter::WriteMethodPool(Sema &SemaRef) {
+  using namespace llvm;
+
+  // Create and write out the blob that contains the instance and
+  // factor method pools.
+  bool Empty = true;
+  {
+    OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator;
+
+    // Create the on-disk hash table representation. Start by
+    // iterating through the instance method pool.
+    PCHMethodPoolTrait::key_type Key;
+    unsigned NumSelectorsInMethodPool = 0;
+    for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
+           Instance = SemaRef.InstanceMethodPool.begin(),
+           InstanceEnd = SemaRef.InstanceMethodPool.end();
+         Instance != InstanceEnd; ++Instance) {
+      // Check whether there is a factory method with the same
+      // selector.
+      llvm::DenseMap<Selector, ObjCMethodList>::iterator Factory
+        = SemaRef.FactoryMethodPool.find(Instance->first);
+
+      if (Factory == SemaRef.FactoryMethodPool.end())
+        Generator.insert(Instance->first,
+                         std::make_pair(Instance->second,
+                                        ObjCMethodList()));
+      else
+        Generator.insert(Instance->first,
+                         std::make_pair(Instance->second, Factory->second));
+
+      ++NumSelectorsInMethodPool;
+      Empty = false;
+    }
+
+    // Now iterate through the factory method pool, to pick up any
+    // selectors that weren't already in the instance method pool.
+    for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
+           Factory = SemaRef.FactoryMethodPool.begin(),
+           FactoryEnd = SemaRef.FactoryMethodPool.end();
+         Factory != FactoryEnd; ++Factory) {
+      // Check whether there is an instance method with the same
+      // selector. If so, there is no work to do here.
+      llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance
+        = SemaRef.InstanceMethodPool.find(Factory->first);
+
+      if (Instance == SemaRef.InstanceMethodPool.end()) {
+        Generator.insert(Factory->first,
+                         std::make_pair(ObjCMethodList(), Factory->second));
+        ++NumSelectorsInMethodPool;
+      }
+
+      Empty = false;
+    }
+
+    if (Empty && SelectorOffsets.empty())
+      return;
+
+    // Create the on-disk hash table in a buffer.
+    llvm::SmallString<4096> MethodPool;
+    uint32_t BucketOffset;
+    SelectorOffsets.resize(SelVector.size());
+    {
+      PCHMethodPoolTrait Trait(*this);
+      llvm::raw_svector_ostream Out(MethodPool);
+      // Make sure that no bucket is at offset 0
+      clang::io::Emit32(Out, 0);
+      BucketOffset = Generator.Emit(Out, Trait);
+
+      // For every selector that we have seen but which was not
+      // written into the hash table, write the selector itself and
+      // record it's offset.
+      for (unsigned I = 0, N = SelVector.size(); I != N; ++I)
+        if (SelectorOffsets[I] == 0)
+          Trait.EmitKey(Out, SelVector[I], 0);
+    }
+
+    // Create a blob abbreviation
+    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+    Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+    unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev);
+
+    // Write the method pool
+    RecordData Record;
+    Record.push_back(pch::METHOD_POOL);
+    Record.push_back(BucketOffset);
+    Record.push_back(NumSelectorsInMethodPool);
+    Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
+
+    // Create a blob abbreviation for the selector table offsets.
+    Abbrev = new BitCodeAbbrev();
+    Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+    unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+    // Write the selector offsets table.
+    Record.clear();
+    Record.push_back(pch::SELECTOR_OFFSETS);
+    Record.push_back(SelectorOffsets.size());
+    Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
+                              (const char *)&SelectorOffsets.front(),
+                              SelectorOffsets.size() * 4);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Identifier Table Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PCHIdentifierTableTrait {
+  PCHWriter &Writer;
+  Preprocessor &PP;
+
+  /// \brief Determines whether this is an "interesting" identifier
+  /// that needs a full IdentifierInfo structure written into the hash
+  /// table.
+  static bool isInterestingIdentifier(const IdentifierInfo *II) {
+    return II->isPoisoned() ||
+      II->isExtensionToken() ||
+      II->hasMacroDefinition() ||
+      II->getObjCOrBuiltinID() ||
+      II->getFETokenInfo<void>();
+  }
+
+public:
+  typedef const IdentifierInfo* key_type;
+  typedef key_type  key_type_ref;
+
+  typedef pch::IdentID data_type;
+  typedef data_type data_type_ref;
+
+  PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP)
+    : Writer(Writer), PP(PP) { }
+
+  static unsigned ComputeHash(const IdentifierInfo* II) {
+    return llvm::HashString(II->getName());
+  }
+
+  std::pair<unsigned,unsigned>
+    EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
+                      pch::IdentID ID) {
+    unsigned KeyLen = II->getLength() + 1;
+    unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
+    if (isInterestingIdentifier(II)) {
+      DataLen += 2; // 2 bytes for builtin ID, flags
+      if (II->hasMacroDefinition() &&
+          !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro())
+        DataLen += 4;
+      for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
+                                     DEnd = IdentifierResolver::end();
+           D != DEnd; ++D)
+        DataLen += sizeof(pch::DeclID);
+    }
+    clang::io::Emit16(Out, DataLen);
+    // We emit the key length after the data length so that every
+    // string is preceded by a 16-bit length. This matches the PTH
+    // format for storing identifiers.
+    clang::io::Emit16(Out, KeyLen);
+    return std::make_pair(KeyLen, DataLen);
+  }
+
+  void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II,
+               unsigned KeyLen) {
+    // Record the location of the key data.  This is used when generating
+    // the mapping from persistent IDs to strings.
+    Writer.SetIdentifierOffset(II, Out.tell());
+    Out.write(II->getNameStart(), KeyLen);
+  }
+
+  void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
+                pch::IdentID ID, unsigned) {
+    if (!isInterestingIdentifier(II)) {
+      clang::io::Emit32(Out, ID << 1);
+      return;
+    }
+
+    clang::io::Emit32(Out, (ID << 1) | 0x01);
+    uint32_t Bits = 0;
+    bool hasMacroDefinition =
+      II->hasMacroDefinition() &&
+      !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro();
+    Bits = (uint32_t)II->getObjCOrBuiltinID();
+    Bits = (Bits << 1) | unsigned(hasMacroDefinition);
+    Bits = (Bits << 1) | unsigned(II->isExtensionToken());
+    Bits = (Bits << 1) | unsigned(II->isPoisoned());
+    Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
+    clang::io::Emit16(Out, Bits);
+
+    if (hasMacroDefinition)
+      clang::io::Emit32(Out, Writer.getMacroOffset(II));
+
+    // Emit the declaration IDs in reverse order, because the
+    // IdentifierResolver provides the declarations as they would be
+    // visible (e.g., the function "stat" would come before the struct
+    // "stat"), but IdentifierResolver::AddDeclToIdentifierChain()
+    // adds declarations to the end of the list (so we need to see the
+    // struct "status" before the function "status").
+    llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II),
+                                        IdentifierResolver::end());
+    for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
+                                                      DEnd = Decls.rend();
+         D != DEnd; ++D)
+      clang::io::Emit32(Out, Writer.getDeclID(*D));
+  }
+};
+} // end anonymous namespace
+
+/// \brief Write the identifier table into the PCH file.
+///
+/// The identifier table consists of a blob containing string data
+/// (the actual identifiers themselves) and a separate "offsets" index
+/// that maps identifier IDs to locations within the blob.
+void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
+  using namespace llvm;
+
+  // Create and write out the blob that contains the identifier
+  // strings.
+  {
+    OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator;
+
+    // Look for any identifiers that were named while processing the
+    // headers, but are otherwise not needed. We add these to the hash
+    // table to enable checking of the predefines buffer in the case
+    // where the user adds new macro definitions when building the PCH
+    // file.
+    for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
+                                IDEnd = PP.getIdentifierTable().end();
+         ID != IDEnd; ++ID)
+      getIdentifierRef(ID->second);
+
+    // Create the on-disk hash table representation.
+    IdentifierOffsets.resize(IdentifierIDs.size());
+    for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
+           ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
+         ID != IDEnd; ++ID) {
+      assert(ID->first && "NULL identifier in identifier table");
+      Generator.insert(ID->first, ID->second);
+    }
+
+    // Create the on-disk hash table in a buffer.
+    llvm::SmallString<4096> IdentifierTable;
+    uint32_t BucketOffset;
+    {
+      PCHIdentifierTableTrait Trait(*this, PP);
+      llvm::raw_svector_ostream Out(IdentifierTable);
+      // Make sure that no bucket is at offset 0
+      clang::io::Emit32(Out, 0);
+      BucketOffset = Generator.Emit(Out, Trait);
+    }
+
+    // Create a blob abbreviation
+    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+    Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+    unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
+
+    // Write the identifier table
+    RecordData Record;
+    Record.push_back(pch::IDENTIFIER_TABLE);
+    Record.push_back(BucketOffset);
+    Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
+  }
+
+  // Write the offsets table for identifier IDs.
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_OFFSET));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+  unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+  RecordData Record;
+  Record.push_back(pch::IDENTIFIER_OFFSET);
+  Record.push_back(IdentifierOffsets.size());
+  Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
+                            (const char *)&IdentifierOffsets.front(),
+                            IdentifierOffsets.size() * sizeof(uint32_t));
+}
+
+//===----------------------------------------------------------------------===//
+// General Serialization Routines
+//===----------------------------------------------------------------------===//
+
+/// \brief Write a record containing the given attributes.
+void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
+  RecordData Record;
+  for (; Attr; Attr = Attr->getNext()) {
+    Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
+    Record.push_back(Attr->isInherited());
+    switch (Attr->getKind()) {
+    default:
+      assert(0 && "Does not support PCH writing for this attribute yet!");
+      break;
+    case Attr::Alias:
+      AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
+      break;
+
+    case Attr::Aligned:
+      Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
+      break;
+
+    case Attr::AlwaysInline:
+      break;
+
+    case Attr::AnalyzerNoReturn:
+      break;
+
+    case Attr::Annotate:
+      AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
+      break;
+
+    case Attr::AsmLabel:
+      AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
+      break;
+
+    case Attr::BaseCheck:
+      break;
+
+    case Attr::Blocks:
+      Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
+      break;
+
+    case Attr::CDecl:
+      break;
+
+    case Attr::Cleanup:
+      AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
+      break;
+
+    case Attr::Const:
+      break;
+
+    case Attr::Constructor:
+      Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
+      break;
+
+    case Attr::DLLExport:
+    case Attr::DLLImport:
+    case Attr::Deprecated:
+      break;
+
+    case Attr::Destructor:
+      Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
+      break;
+
+    case Attr::FastCall:
+    case Attr::Final:
+      break;
+
+    case Attr::Format: {
+      const FormatAttr *Format = cast<FormatAttr>(Attr);
+      AddString(Format->getType(), Record);
+      Record.push_back(Format->getFormatIdx());
+      Record.push_back(Format->getFirstArg());
+      break;
+    }
+
+    case Attr::FormatArg: {
+      const FormatArgAttr *Format = cast<FormatArgAttr>(Attr);
+      Record.push_back(Format->getFormatIdx());
+      break;
+    }
+
+    case Attr::Sentinel : {
+      const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr);
+      Record.push_back(Sentinel->getSentinel());
+      Record.push_back(Sentinel->getNullPos());
+      break;
+    }
+
+    case Attr::GNUInline:
+    case Attr::Hiding:
+    case Attr::IBOutletKind:
+    case Attr::Malloc:
+    case Attr::NoDebug:
+    case Attr::NoReturn:
+    case Attr::NoThrow:
+    case Attr::NoInline:
+      break;
+
+    case Attr::NonNull: {
+      const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
+      Record.push_back(NonNull->size());
+      Record.insert(Record.end(), NonNull->begin(), NonNull->end());
+      break;
+    }
+
+    case Attr::ObjCException:
+    case Attr::ObjCNSObject:
+    case Attr::CFReturnsRetained:
+    case Attr::NSReturnsRetained:
+    case Attr::Overloadable:
+    case Attr::Override:
+      break;
+
+    case Attr::PragmaPack:
+      Record.push_back(cast<PragmaPackAttr>(Attr)->getAlignment());
+      break;
+
+    case Attr::Packed:
+      break;
+
+    case Attr::Pure:
+      break;
+
+    case Attr::Regparm:
+      Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
+      break;
+
+    case Attr::ReqdWorkGroupSize:
+      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
+      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
+      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
+      break;
+
+    case Attr::Section:
+      AddString(cast<SectionAttr>(Attr)->getName(), Record);
+      break;
+
+    case Attr::StdCall:
+    case Attr::TransparentUnion:
+    case Attr::Unavailable:
+    case Attr::Unused:
+    case Attr::Used:
+      break;
+
+    case Attr::Visibility:
+      // FIXME: stable encoding
+      Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
+      break;
+
+    case Attr::WarnUnusedResult:
+    case Attr::Weak:
+    case Attr::WeakImport:
+      break;
+    }
+  }
+
+  Stream.EmitRecord(pch::DECL_ATTR, Record);
+}
+
+void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
+  Record.push_back(Str.size());
+  Record.insert(Record.end(), Str.begin(), Str.end());
+}
+
+/// \brief Note that the identifier II occurs at the given offset
+/// within the identifier table.
+void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
+  IdentifierOffsets[IdentifierIDs[II] - 1] = Offset;
+}
+
+/// \brief Note that the selector Sel occurs at the given offset
+/// within the method pool/selector table.
+void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
+  unsigned ID = SelectorIDs[Sel];
+  assert(ID && "Unknown selector");
+  SelectorOffsets[ID - 1] = Offset;
+}
+
+PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
+  : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS),
+    NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
+    NumVisibleDeclContexts(0) { }
+
+void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+                         const char *isysroot) {
+  using namespace llvm;
+
+  ASTContext &Context = SemaRef.Context;
+  Preprocessor &PP = SemaRef.PP;
+
+  // Emit the file header.
+  Stream.Emit((unsigned)'C', 8);
+  Stream.Emit((unsigned)'P', 8);
+  Stream.Emit((unsigned)'C', 8);
+  Stream.Emit((unsigned)'H', 8);
+
+  WriteBlockInfoBlock();
+
+  // The translation unit is the first declaration we'll emit.
+  DeclIDs[Context.getTranslationUnitDecl()] = 1;
+  DeclTypesToEmit.push(Context.getTranslationUnitDecl());
+
+  // Make sure that we emit IdentifierInfos (and any attached
+  // declarations) for builtins.
+  {
+    IdentifierTable &Table = PP.getIdentifierTable();
+    llvm::SmallVector<const char *, 32> BuiltinNames;
+    Context.BuiltinInfo.GetBuiltinNames(BuiltinNames,
+                                        Context.getLangOptions().NoBuiltin);
+    for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
+      getIdentifierRef(&Table.get(BuiltinNames[I]));
+  }
+
+  // Build a record containing all of the tentative definitions in this file, in
+  // TentativeDefinitions order.  Generally, this record will be empty for
+  // headers.
+  RecordData TentativeDefinitions;
+  for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
+    AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
+  }
+
+  // Build a record containing all of the locally-scoped external
+  // declarations in this header file. Generally, this record will be
+  // empty.
+  RecordData LocallyScopedExternalDecls;
+  // FIXME: This is filling in the PCH file in densemap order which is
+  // nondeterminstic!
+  for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
+         TD = SemaRef.LocallyScopedExternalDecls.begin(),
+         TDEnd = SemaRef.LocallyScopedExternalDecls.end();
+       TD != TDEnd; ++TD)
+    AddDeclRef(TD->second, LocallyScopedExternalDecls);
+
+  // Build a record containing all of the ext_vector declarations.
+  RecordData ExtVectorDecls;
+  for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I)
+    AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
+
+  // Write the remaining PCH contents.
+  RecordData Record;
+  Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
+  WriteMetadata(Context, isysroot);
+  WriteLanguageOptions(Context.getLangOptions());
+  if (StatCalls && !isysroot)
+    WriteStatCache(*StatCalls, isysroot);
+  WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+  WriteComments(Context);
+  // Write the record of special types.
+  Record.clear();
+
+  AddTypeRef(Context.getBuiltinVaListType(), Record);
+  AddTypeRef(Context.getObjCIdType(), Record);
+  AddTypeRef(Context.getObjCSelType(), Record);
+  AddTypeRef(Context.getObjCProtoType(), Record);
+  AddTypeRef(Context.getObjCClassType(), Record);
+  AddTypeRef(Context.getRawCFConstantStringType(), Record);
+  AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record);
+  AddTypeRef(Context.getFILEType(), Record);
+  AddTypeRef(Context.getjmp_bufType(), Record);
+  AddTypeRef(Context.getsigjmp_bufType(), Record);
+  AddTypeRef(Context.ObjCIdRedefinitionType, Record);
+  AddTypeRef(Context.ObjCClassRedefinitionType, Record);
+#if 0
+  // FIXME. Accommodate for this in several PCH/Indexer tests
+  AddTypeRef(Context.ObjCSelRedefinitionType, Record);
+#endif
+  AddTypeRef(Context.getRawBlockdescriptorType(), Record);
+  AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
+  Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
+
+  // Keep writing types and declarations until all types and
+  // declarations have been written.
+  Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
+  WriteDeclsBlockAbbrevs();
+  while (!DeclTypesToEmit.empty()) {
+    DeclOrType DOT = DeclTypesToEmit.front();
+    DeclTypesToEmit.pop();
+    if (DOT.isType())
+      WriteType(DOT.getType());
+    else
+      WriteDecl(Context, DOT.getDecl());
+  }
+  Stream.ExitBlock();
+  
+  WritePreprocessor(PP);
+  WriteMethodPool(SemaRef);
+  WriteIdentifierTable(PP);
+
+  // Write the type offsets array
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
+  unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+  Record.clear();
+  Record.push_back(pch::TYPE_OFFSET);
+  Record.push_back(TypeOffsets.size());
+  Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
+                            (const char *)&TypeOffsets.front(),
+                            TypeOffsets.size() * sizeof(TypeOffsets[0]));
+
+  // Write the declaration offsets array
+  Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
+  unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+  Record.clear();
+  Record.push_back(pch::DECL_OFFSET);
+  Record.push_back(DeclOffsets.size());
+  Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
+                            (const char *)&DeclOffsets.front(),
+                            DeclOffsets.size() * sizeof(DeclOffsets[0]));
+
+  // Write the record containing external, unnamed definitions.
+  if (!ExternalDefinitions.empty())
+    Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
+
+  // Write the record containing tentative definitions.
+  if (!TentativeDefinitions.empty())
+    Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions);
+
+  // Write the record containing locally-scoped external definitions.
+  if (!LocallyScopedExternalDecls.empty())
+    Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
+                      LocallyScopedExternalDecls);
+
+  // Write the record containing ext_vector type names.
+  if (!ExtVectorDecls.empty())
+    Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls);
+
+  // Some simple statistics
+  Record.clear();
+  Record.push_back(NumStatements);
+  Record.push_back(NumMacros);
+  Record.push_back(NumLexicalDeclContexts);
+  Record.push_back(NumVisibleDeclContexts);
+  Stream.EmitRecord(pch::STATISTICS, Record);
+  Stream.ExitBlock();
+}
+
+void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
+  Record.push_back(Loc.getRawEncoding());
+}
+
+void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
+  Record.push_back(Value.getBitWidth());
+  unsigned N = Value.getNumWords();
+  const uint64_t* Words = Value.getRawData();
+  for (unsigned I = 0; I != N; ++I)
+    Record.push_back(Words[I]);
+}
+
+void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
+  Record.push_back(Value.isUnsigned());
+  AddAPInt(Value, Record);
+}
+
+void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
+  AddAPInt(Value.bitcastToAPInt(), Record);
+}
+
+void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
+  Record.push_back(getIdentifierRef(II));
+}
+
+pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) {
+  if (II == 0)
+    return 0;
+
+  pch::IdentID &ID = IdentifierIDs[II];
+  if (ID == 0)
+    ID = IdentifierIDs.size();
+  return ID;
+}
+
+void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
+  if (SelRef.getAsOpaquePtr() == 0) {
+    Record.push_back(0);
+    return;
+  }
+
+  pch::SelectorID &SID = SelectorIDs[SelRef];
+  if (SID == 0) {
+    SID = SelectorIDs.size();
+    SelVector.push_back(SelRef);
+  }
+  Record.push_back(SID);
+}
+
+void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+                                       RecordData &Record) {
+  switch (Arg.getArgument().getKind()) {
+  case TemplateArgument::Expression:
+    AddStmt(Arg.getLocInfo().getAsExpr());
+    break;
+  case TemplateArgument::Type:
+    AddTypeSourceInfo(Arg.getLocInfo().getAsTypeSourceInfo(), Record);
+    break;
+  case TemplateArgument::Template:
+    Record.push_back(
+                   Arg.getTemplateQualifierRange().getBegin().getRawEncoding());
+    Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding());
+    Record.push_back(Arg.getTemplateNameLoc().getRawEncoding());
+    break;
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Pack:
+    break;
+  }
+}
+
+void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
+  if (TInfo == 0) {
+    AddTypeRef(QualType(), Record);
+    return;
+  }
+
+  AddTypeRef(TInfo->getType(), Record);
+  TypeLocWriter TLW(*this, Record);
+  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+    TLW.Visit(TL);  
+}
+
+void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
+  if (T.isNull()) {
+    Record.push_back(pch::PREDEF_TYPE_NULL_ID);
+    return;
+  }
+
+  unsigned FastQuals = T.getLocalFastQualifiers();
+  T.removeFastQualifiers();
+
+  if (T.hasLocalNonFastQualifiers()) {
+    pch::TypeID &ID = TypeIDs[T];
+    if (ID == 0) {
+      // We haven't seen these qualifiers applied to this type before.
+      // Assign it a new ID.  This is the only time we enqueue a
+      // qualified type, and it has no CV qualifiers.
+      ID = NextTypeID++;
+      DeclTypesToEmit.push(T);
+    }
+    
+    // Encode the type qualifiers in the type reference.
+    Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
+    return;
+  }
+
+  assert(!T.hasLocalQualifiers());
+  
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
+    pch::TypeID ID = 0;
+    switch (BT->getKind()) {
+    case BuiltinType::Void:       ID = pch::PREDEF_TYPE_VOID_ID;       break;
+    case BuiltinType::Bool:       ID = pch::PREDEF_TYPE_BOOL_ID;       break;
+    case BuiltinType::Char_U:     ID = pch::PREDEF_TYPE_CHAR_U_ID;     break;
+    case BuiltinType::UChar:      ID = pch::PREDEF_TYPE_UCHAR_ID;      break;
+    case BuiltinType::UShort:     ID = pch::PREDEF_TYPE_USHORT_ID;     break;
+    case BuiltinType::UInt:       ID = pch::PREDEF_TYPE_UINT_ID;       break;
+    case BuiltinType::ULong:      ID = pch::PREDEF_TYPE_ULONG_ID;      break;
+    case BuiltinType::ULongLong:  ID = pch::PREDEF_TYPE_ULONGLONG_ID;  break;
+    case BuiltinType::UInt128:    ID = pch::PREDEF_TYPE_UINT128_ID;    break;
+    case BuiltinType::Char_S:     ID = pch::PREDEF_TYPE_CHAR_S_ID;     break;
+    case BuiltinType::SChar:      ID = pch::PREDEF_TYPE_SCHAR_ID;      break;
+    case BuiltinType::WChar:      ID = pch::PREDEF_TYPE_WCHAR_ID;      break;
+    case BuiltinType::Short:      ID = pch::PREDEF_TYPE_SHORT_ID;      break;
+    case BuiltinType::Int:        ID = pch::PREDEF_TYPE_INT_ID;        break;
+    case BuiltinType::Long:       ID = pch::PREDEF_TYPE_LONG_ID;       break;
+    case BuiltinType::LongLong:   ID = pch::PREDEF_TYPE_LONGLONG_ID;   break;
+    case BuiltinType::Int128:     ID = pch::PREDEF_TYPE_INT128_ID;     break;
+    case BuiltinType::Float:      ID = pch::PREDEF_TYPE_FLOAT_ID;      break;
+    case BuiltinType::Double:     ID = pch::PREDEF_TYPE_DOUBLE_ID;     break;
+    case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
+    case BuiltinType::NullPtr:    ID = pch::PREDEF_TYPE_NULLPTR_ID;    break;
+    case BuiltinType::Char16:     ID = pch::PREDEF_TYPE_CHAR16_ID;     break;
+    case BuiltinType::Char32:     ID = pch::PREDEF_TYPE_CHAR32_ID;     break;
+    case BuiltinType::Overload:   ID = pch::PREDEF_TYPE_OVERLOAD_ID;   break;
+    case BuiltinType::Dependent:  ID = pch::PREDEF_TYPE_DEPENDENT_ID;  break;
+    case BuiltinType::ObjCId:     ID = pch::PREDEF_TYPE_OBJC_ID;       break;
+    case BuiltinType::ObjCClass:  ID = pch::PREDEF_TYPE_OBJC_CLASS;    break;
+    case BuiltinType::ObjCSel:    ID = pch::PREDEF_TYPE_OBJC_SEL;      break;
+    case BuiltinType::UndeducedAuto:
+      assert(0 && "Should not see undeduced auto here");
+      break;
+    }
+
+    Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
+    return;
+  }
+
+  pch::TypeID &ID = TypeIDs[T];
+  if (ID == 0) {
+    // We haven't seen this type before. Assign it a new ID and put it
+    // into the queue of types to emit.
+    ID = NextTypeID++;
+    DeclTypesToEmit.push(T);
+  }
+
+  // Encode the type qualifiers in the type reference.
+  Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
+}
+
+void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
+  if (D == 0) {
+    Record.push_back(0);
+    return;
+  }
+
+  pch::DeclID &ID = DeclIDs[D];
+  if (ID == 0) {
+    // We haven't seen this declaration before. Give it a new ID and
+    // enqueue it in the list of declarations to emit.
+    ID = DeclIDs.size();
+    DeclTypesToEmit.push(const_cast<Decl *>(D));
+  }
+
+  Record.push_back(ID);
+}
+
+pch::DeclID PCHWriter::getDeclID(const Decl *D) {
+  if (D == 0)
+    return 0;
+
+  assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!");
+  return DeclIDs[D];
+}
+
+void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
+  // FIXME: Emit a stable enum for NameKind.  0 = Identifier etc.
+  Record.push_back(Name.getNameKind());
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+    AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
+    break;
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    AddSelectorRef(Name.getObjCSelector(), Record);
+    break;
+
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+    AddTypeRef(Name.getCXXNameType(), Record);
+    break;
+
+  case DeclarationName::CXXOperatorName:
+    Record.push_back(Name.getCXXOverloadedOperator());
+    break;
+
+  case DeclarationName::CXXLiteralOperatorName:
+    AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record);
+    break;
+
+  case DeclarationName::CXXUsingDirective:
+    // No extra data to emit
+    break;
+  }
+}
+
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
new file mode 100644
index 0000000..1901b2f
--- /dev/null
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -0,0 +1,611 @@
+//===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements serialization for Declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHWriter.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Declaration serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
+
+    PCHWriter &Writer;
+    ASTContext &Context;
+    PCHWriter::RecordData &Record;
+
+  public:
+    pch::DeclCode Code;
+    unsigned AbbrevToUse;
+
+    PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
+                  PCHWriter::RecordData &Record)
+      : Writer(Writer), Context(Context), Record(Record) {
+    }
+
+    void VisitDecl(Decl *D);
+    void VisitTranslationUnitDecl(TranslationUnitDecl *D);
+    void VisitNamedDecl(NamedDecl *D);
+    void VisitTypeDecl(TypeDecl *D);
+    void VisitTypedefDecl(TypedefDecl *D);
+    void VisitTagDecl(TagDecl *D);
+    void VisitEnumDecl(EnumDecl *D);
+    void VisitRecordDecl(RecordDecl *D);
+    void VisitValueDecl(ValueDecl *D);
+    void VisitEnumConstantDecl(EnumConstantDecl *D);
+    void VisitDeclaratorDecl(DeclaratorDecl *D);
+    void VisitFunctionDecl(FunctionDecl *D);
+    void VisitFieldDecl(FieldDecl *D);
+    void VisitVarDecl(VarDecl *D);
+    void VisitImplicitParamDecl(ImplicitParamDecl *D);
+    void VisitParmVarDecl(ParmVarDecl *D);
+    void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
+    void VisitBlockDecl(BlockDecl *D);
+    void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+                          uint64_t VisibleOffset);
+    void VisitObjCMethodDecl(ObjCMethodDecl *D);
+    void VisitObjCContainerDecl(ObjCContainerDecl *D);
+    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+    void VisitObjCIvarDecl(ObjCIvarDecl *D);
+    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+    void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
+    void VisitObjCClassDecl(ObjCClassDecl *D);
+    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+    void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
+    void VisitObjCImplDecl(ObjCImplDecl *D);
+    void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+    void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+    void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
+    void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+    void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+  };
+}
+
+void PCHDeclWriter::VisitDecl(Decl *D) {
+  Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
+  Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
+  Writer.AddSourceLocation(D->getLocation(), Record);
+  Record.push_back(D->isInvalidDecl());
+  Record.push_back(D->hasAttrs());
+  Record.push_back(D->isImplicit());
+  Record.push_back(D->isUsed());
+  Record.push_back(D->getAccess());
+  Record.push_back(D->getPCHLevel());
+}
+
+void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+  VisitDecl(D);
+  Code = pch::DECL_TRANSLATION_UNIT;
+}
+
+void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
+  VisitDecl(D);
+  Writer.AddDeclarationName(D->getDeclName(), Record);
+}
+
+void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+}
+
+void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+  VisitTypeDecl(D);
+  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+  Code = pch::DECL_TYPEDEF;
+}
+
+void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
+  VisitTypeDecl(D);
+  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
+  Record.push_back(D->isDefinition());
+  Record.push_back(D->isDefinedInDeclarator());
+  Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
+  Writer.AddSourceLocation(D->getRBraceLoc(), Record);
+  Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
+}
+
+void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
+  VisitTagDecl(D);
+  Writer.AddTypeRef(D->getIntegerType(), Record);
+  Writer.AddTypeRef(D->getPromotionType(), Record);
+  // FIXME: C++ InstantiatedFrom
+  Code = pch::DECL_ENUM;
+}
+
+void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
+  VisitTagDecl(D);
+  Record.push_back(D->hasFlexibleArrayMember());
+  Record.push_back(D->isAnonymousStructOrUnion());
+  Record.push_back(D->hasObjectMember());
+  Code = pch::DECL_RECORD;
+}
+
+void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddTypeRef(D->getType(), Record);
+}
+
+void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+  VisitValueDecl(D);
+  Record.push_back(D->getInitExpr()? 1 : 0);
+  if (D->getInitExpr())
+    Writer.AddStmt(D->getInitExpr());
+  Writer.AddAPSInt(D->getInitVal(), Record);
+  Code = pch::DECL_ENUM_CONSTANT;
+}
+
+void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
+  VisitValueDecl(D);
+  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+}
+
+void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
+  VisitDeclaratorDecl(D);
+  Record.push_back(D->isThisDeclarationADefinition());
+  if (D->isThisDeclarationADefinition())
+    Writer.AddStmt(D->getBody());
+  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+  Record.push_back(D->isInlineSpecified());
+  Record.push_back(D->isVirtualAsWritten());
+  Record.push_back(D->isPure());
+  Record.push_back(D->hasInheritedPrototype());
+  Record.push_back(D->hasWrittenPrototype());
+  Record.push_back(D->isDeleted());
+  Record.push_back(D->isTrivial());
+  Record.push_back(D->isCopyAssignment());
+  Record.push_back(D->hasImplicitReturnZero());
+  Writer.AddSourceLocation(D->getLocEnd(), Record);
+  // FIXME: C++ TemplateOrInstantiation
+  Record.push_back(D->param_size());
+  for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
+       P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  Code = pch::DECL_FUNCTION;
+}
+
+void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+  VisitNamedDecl(D);
+  // FIXME: convert to LazyStmtPtr?
+  // Unlike C/C++, method bodies will never be in header files.
+  Record.push_back(D->getBody() != 0);
+  if (D->getBody() != 0) {
+    Writer.AddStmt(D->getBody());
+    Writer.AddDeclRef(D->getSelfDecl(), Record);
+    Writer.AddDeclRef(D->getCmdDecl(), Record);
+  }
+  Record.push_back(D->isInstanceMethod());
+  Record.push_back(D->isVariadic());
+  Record.push_back(D->isSynthesized());
+  // FIXME: stable encoding for @required/@optional
+  Record.push_back(D->getImplementationControl());
+  // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
+  Record.push_back(D->getObjCDeclQualifier());
+  Writer.AddTypeRef(D->getResultType(), Record);
+  Writer.AddSourceLocation(D->getLocEnd(), Record);
+  Record.push_back(D->param_size());
+  for (ObjCMethodDecl::param_iterator P = D->param_begin(),
+                                   PEnd = D->param_end(); P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  Code = pch::DECL_OBJC_METHOD;
+}
+
+void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+  VisitNamedDecl(D);
+  SourceRange R = D->getAtEndRange();
+  Writer.AddSourceLocation(R.getBegin(), Record);
+  Writer.AddSourceLocation(R.getEnd(), Record);
+  // Abstract class (no need to define a stable pch::DECL code).
+}
+
+void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+  VisitObjCContainerDecl(D);
+  Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+  Writer.AddDeclRef(D->getSuperClass(), Record);
+  Record.push_back(D->protocol_size());
+  for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
+         PEnd = D->protocol_end();
+       P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+         PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
+  Record.push_back(D->ivar_size());
+  for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
+                                     IEnd = D->ivar_end(); I != IEnd; ++I)
+    Writer.AddDeclRef(*I, Record);
+  Writer.AddDeclRef(D->getCategoryList(), Record);
+  Record.push_back(D->isForwardDecl());
+  Record.push_back(D->isImplicitInterfaceDecl());
+  Writer.AddSourceLocation(D->getClassLoc(), Record);
+  Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
+  Writer.AddSourceLocation(D->getLocEnd(), Record);
+  Code = pch::DECL_OBJC_INTERFACE;
+}
+
+void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
+  VisitFieldDecl(D);
+  // FIXME: stable encoding for @public/@private/@protected/@package
+  Record.push_back(D->getAccessControl());
+  Code = pch::DECL_OBJC_IVAR;
+}
+
+void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+  VisitObjCContainerDecl(D);
+  Record.push_back(D->isForwardDecl());
+  Writer.AddSourceLocation(D->getLocEnd(), Record);
+  Record.push_back(D->protocol_size());
+  for (ObjCProtocolDecl::protocol_iterator
+       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+    Writer.AddDeclRef(*I, Record);
+  for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+         PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
+  Code = pch::DECL_OBJC_PROTOCOL;
+}
+
+void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
+  VisitFieldDecl(D);
+  Code = pch::DECL_OBJC_AT_DEFS_FIELD;
+}
+
+void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
+  VisitDecl(D);
+  Record.push_back(D->size());
+  for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
+    Writer.AddDeclRef(I->getInterface(), Record);
+  for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
+    Writer.AddSourceLocation(I->getLocation(), Record);
+  Code = pch::DECL_OBJC_CLASS;
+}
+
+void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+  VisitDecl(D);
+  Record.push_back(D->protocol_size());
+  for (ObjCForwardProtocolDecl::protocol_iterator
+       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+    Writer.AddDeclRef(*I, Record);
+  for (ObjCForwardProtocolDecl::protocol_loc_iterator 
+         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
+  Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
+}
+
+void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
+  VisitObjCContainerDecl(D);
+  Writer.AddDeclRef(D->getClassInterface(), Record);
+  Record.push_back(D->protocol_size());
+  for (ObjCCategoryDecl::protocol_iterator
+       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+    Writer.AddDeclRef(*I, Record);
+  for (ObjCCategoryDecl::protocol_loc_iterator 
+         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
+  Writer.AddDeclRef(D->getNextClassCategory(), Record);
+  Writer.AddSourceLocation(D->getAtLoc(), Record);
+  Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
+  Code = pch::DECL_OBJC_CATEGORY;
+}
+
+void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddDeclRef(D->getClassInterface(), Record);
+  Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
+}
+
+void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddSourceLocation(D->getAtLoc(), Record);
+  Writer.AddTypeRef(D->getType(), Record);
+  // FIXME: stable encoding
+  Record.push_back((unsigned)D->getPropertyAttributes());
+  // FIXME: stable encoding
+  Record.push_back((unsigned)D->getPropertyImplementation());
+  Writer.AddDeclarationName(D->getGetterName(), Record);
+  Writer.AddDeclarationName(D->getSetterName(), Record);
+  Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
+  Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
+  Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
+  Code = pch::DECL_OBJC_PROPERTY;
+}
+
+void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
+  VisitObjCContainerDecl(D);
+  Writer.AddDeclRef(D->getClassInterface(), Record);
+  // Abstract class (no need to define a stable pch::DECL code).
+}
+
+void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+  VisitObjCImplDecl(D);
+  Writer.AddIdentifierRef(D->getIdentifier(), Record);
+  Code = pch::DECL_OBJC_CATEGORY_IMPL;
+}
+
+void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+  VisitObjCImplDecl(D);
+  Writer.AddDeclRef(D->getSuperClass(), Record);
+  Code = pch::DECL_OBJC_IMPLEMENTATION;
+}
+
+void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+  VisitDecl(D);
+  Writer.AddSourceLocation(D->getLocStart(), Record);
+  Writer.AddDeclRef(D->getPropertyDecl(), Record);
+  Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
+  Code = pch::DECL_OBJC_PROPERTY_IMPL;
+}
+
+void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
+  VisitDeclaratorDecl(D);
+  Record.push_back(D->isMutable());
+  Record.push_back(D->getBitWidth()? 1 : 0);
+  if (D->getBitWidth())
+    Writer.AddStmt(D->getBitWidth());
+  Code = pch::DECL_FIELD;
+}
+
+void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
+  VisitDeclaratorDecl(D);
+  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+  Record.push_back(D->isThreadSpecified());
+  Record.push_back(D->hasCXXDirectInitializer());
+  Record.push_back(D->isDeclaredInCondition());
+  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  Record.push_back(D->getInit()? 1 : 0);
+  if (D->getInit())
+    Writer.AddStmt(D->getInit());
+  Code = pch::DECL_VAR;
+}
+
+void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
+  VisitVarDecl(D);
+  Code = pch::DECL_IMPLICIT_PARAM;
+}
+
+void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
+  VisitVarDecl(D);
+  Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
+  Code = pch::DECL_PARM_VAR;
+
+
+  // If the assumptions about the DECL_PARM_VAR abbrev are true, use it.  Here
+  // we dynamically check for the properties that we optimize for, but don't
+  // know are true of all PARM_VAR_DECLs.
+  if (!D->getTypeSourceInfo() &&
+      !D->hasAttrs() &&
+      !D->isImplicit() &&
+      !D->isUsed() &&
+      D->getAccess() == AS_none &&
+      D->getPCHLevel() == 0 &&
+      D->getStorageClass() == 0 &&
+      !D->hasCXXDirectInitializer() && // Can params have this ever?
+      D->getObjCDeclQualifier() == 0)
+    AbbrevToUse = Writer.getParmVarDeclAbbrev();
+
+  // Check things we know are true of *every* PARM_VAR_DECL, which is more than
+  // just us assuming it.
+  assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
+  assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
+  assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
+  assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition");
+  assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
+  assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
+}
+
+void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
+  VisitDecl(D);
+  Writer.AddStmt(D->getAsmString());
+  Code = pch::DECL_FILE_SCOPE_ASM;
+}
+
+void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
+  VisitDecl(D);
+  Writer.AddStmt(D->getBody());
+  Record.push_back(D->param_size());
+  for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
+       P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  Code = pch::DECL_BLOCK;
+}
+
+/// \brief Emit the DeclContext part of a declaration context decl.
+///
+/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
+/// block for this declaration context is stored. May be 0 to indicate
+/// that there are no declarations stored within this context.
+///
+/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
+/// block for this declaration context is stored. May be 0 to indicate
+/// that there are no declarations visible from this context. Note
+/// that this value will not be emitted for non-primary declaration
+/// contexts.
+void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+                                     uint64_t VisibleOffset) {
+  Record.push_back(LexicalOffset);
+  Record.push_back(VisibleOffset);
+}
+
+
+//===----------------------------------------------------------------------===//
+// PCHWriter Implementation
+//===----------------------------------------------------------------------===//
+
+void PCHWriter::WriteDeclsBlockAbbrevs() {
+  using namespace llvm;
+  // Abbreviation for DECL_PARM_VAR.
+  BitCodeAbbrev *Abv = new BitCodeAbbrev();
+  Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR));
+
+  // Decl
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
+  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl (!?)
+  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs
+  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit
+  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed
+  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
+  Abv->Add(BitCodeAbbrevOp(0));                       // PCH level
+
+  // NamedDecl
+  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+  // ValueDecl
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
+  // DeclaratorDecl
+  Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType
+  // VarDecl
+  Abv->Add(BitCodeAbbrevOp(0));                       // StorageClass
+  Abv->Add(BitCodeAbbrevOp(0));                       // isThreadSpecified
+  Abv->Add(BitCodeAbbrevOp(0));                       // hasCXXDirectInitializer
+  Abv->Add(BitCodeAbbrevOp(0));                       // isDeclaredInCondition
+  Abv->Add(BitCodeAbbrevOp(0));                       // PrevDecl
+  Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
+  // ParmVarDecl
+  Abv->Add(BitCodeAbbrevOp(0));                       // ObjCDeclQualifier
+
+  ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
+}
+
+/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
+/// consumers of the AST.
+///
+/// Such decls will always be deserialized from the PCH file, so we would like
+/// this to be as restrictive as possible. Currently the predicate is driven by
+/// code generation requirements, if other clients have a different notion of
+/// what is "required" then we may have to consider an alternate scheme where
+/// clients can iterate over the top-level decls and get information on them,
+/// without necessary deserializing them. We could explicitly require such
+/// clients to use a separate API call to "realize" the decl. This should be
+/// relatively painless since they would presumably only do it for top-level
+/// decls.
+//
+// FIXME: This predicate is essentially IRgen's predicate to determine whether a
+// declaration can be deferred. Merge them somehow.
+static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
+  // File scoped assembly must be seen.
+  if (isa<FileScopeAsmDecl>(D))
+    return true;
+
+  // Otherwise if this isn't a function or a file scoped variable it doesn't
+  // need to be seen.
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (!VD->isFileVarDecl())
+      return false;
+  } else if (!isa<FunctionDecl>(D))
+    return false;
+
+  // Aliases and used decls must be seen.
+  if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
+    return true;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // Forward declarations don't need to be seen.
+    if (!FD->isThisDeclarationADefinition())
+      return false;
+
+    // Constructors and destructors must be seen.
+    if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+      return true;
+
+    // Otherwise, this is required unless it is static.
+    //
+    // FIXME: Inlines.
+    return FD->getStorageClass() != FunctionDecl::Static;
+  } else {
+    const VarDecl *VD = cast<VarDecl>(D);
+
+    // In C++, this doesn't need to be seen if it is marked "extern".
+    if (Context.getLangOptions().CPlusPlus && !VD->getInit() &&
+        (VD->getStorageClass() == VarDecl::Extern ||
+         VD->isExternC()))
+      return false;
+
+    // In C, this doesn't need to be seen unless it is a definition.
+    if (!Context.getLangOptions().CPlusPlus && !VD->getInit())
+      return false;
+
+    // Otherwise, this is required unless it is static.
+    return VD->getStorageClass() != VarDecl::Static;
+  }
+}
+
+void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
+  RecordData Record;
+  PCHDeclWriter W(*this, Context, Record);
+
+  // If this declaration is also a DeclContext, write blocks for the
+  // declarations that lexically stored inside its context and those
+  // declarations that are visible from its context. These blocks
+  // are written before the declaration itself so that we can put
+  // their offsets into the record for the declaration.
+  uint64_t LexicalOffset = 0;
+  uint64_t VisibleOffset = 0;
+  DeclContext *DC = dyn_cast<DeclContext>(D);
+  if (DC) {
+    LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
+    VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
+  }
+
+  // Determine the ID for this declaration
+  pch::DeclID &ID = DeclIDs[D];
+  if (ID == 0)
+    ID = DeclIDs.size();
+
+  unsigned Index = ID - 1;
+
+  // Record the offset for this declaration
+  if (DeclOffsets.size() == Index)
+    DeclOffsets.push_back(Stream.GetCurrentBitNo());
+  else if (DeclOffsets.size() < Index) {
+    DeclOffsets.resize(Index+1);
+    DeclOffsets[Index] = Stream.GetCurrentBitNo();
+  }
+
+  // Build and emit a record for this declaration
+  Record.clear();
+  W.Code = (pch::DeclCode)0;
+  W.AbbrevToUse = 0;
+  W.Visit(D);
+  if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+
+  if (!W.Code)
+    llvm::llvm_report_error(llvm::StringRef("unexpected declaration kind '") +
+                            D->getDeclKindName() + "'");
+  Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
+
+  // If the declaration had any attributes, write them now.
+  if (D->hasAttrs())
+    WriteAttributeRecord(D->getAttrs());
+
+  // Flush any expressions that were written as part of this declaration.
+  FlushStmts();
+
+  // Note "external" declarations so that we can add them to a record in the
+  // PCH file later.
+  //
+  // FIXME: This should be renamed, the predicate is much more complicated.
+  if (isRequiredDecl(D, Context))
+    ExternalDefinitions.push_back(Index + 1);
+}
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
new file mode 100644
index 0000000..a8cc9d6
--- /dev/null
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -0,0 +1,933 @@
+//===--- PCHWriterStmt.cpp - Statement and Expression Serialization -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements serialization for Statements and Expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PCHWriter.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Statement/expression serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class PCHStmtWriter : public StmtVisitor<PCHStmtWriter, void> {
+    PCHWriter &Writer;
+    PCHWriter::RecordData &Record;
+
+  public:
+    pch::StmtCode Code;
+
+    PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+      : Writer(Writer), Record(Record) { }
+
+    void VisitStmt(Stmt *S);
+    void VisitNullStmt(NullStmt *S);
+    void VisitCompoundStmt(CompoundStmt *S);
+    void VisitSwitchCase(SwitchCase *S);
+    void VisitCaseStmt(CaseStmt *S);
+    void VisitDefaultStmt(DefaultStmt *S);
+    void VisitLabelStmt(LabelStmt *S);
+    void VisitIfStmt(IfStmt *S);
+    void VisitSwitchStmt(SwitchStmt *S);
+    void VisitWhileStmt(WhileStmt *S);
+    void VisitDoStmt(DoStmt *S);
+    void VisitForStmt(ForStmt *S);
+    void VisitGotoStmt(GotoStmt *S);
+    void VisitIndirectGotoStmt(IndirectGotoStmt *S);
+    void VisitContinueStmt(ContinueStmt *S);
+    void VisitBreakStmt(BreakStmt *S);
+    void VisitReturnStmt(ReturnStmt *S);
+    void VisitDeclStmt(DeclStmt *S);
+    void VisitAsmStmt(AsmStmt *S);
+    void VisitExpr(Expr *E);
+    void VisitPredefinedExpr(PredefinedExpr *E);
+    void VisitDeclRefExpr(DeclRefExpr *E);
+    void VisitIntegerLiteral(IntegerLiteral *E);
+    void VisitFloatingLiteral(FloatingLiteral *E);
+    void VisitImaginaryLiteral(ImaginaryLiteral *E);
+    void VisitStringLiteral(StringLiteral *E);
+    void VisitCharacterLiteral(CharacterLiteral *E);
+    void VisitParenExpr(ParenExpr *E);
+    void VisitUnaryOperator(UnaryOperator *E);
+    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+    void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+    void VisitCallExpr(CallExpr *E);
+    void VisitMemberExpr(MemberExpr *E);
+    void VisitCastExpr(CastExpr *E);
+    void VisitBinaryOperator(BinaryOperator *E);
+    void VisitCompoundAssignOperator(CompoundAssignOperator *E);
+    void VisitConditionalOperator(ConditionalOperator *E);
+    void VisitImplicitCastExpr(ImplicitCastExpr *E);
+    void VisitExplicitCastExpr(ExplicitCastExpr *E);
+    void VisitCStyleCastExpr(CStyleCastExpr *E);
+    void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+    void VisitExtVectorElementExpr(ExtVectorElementExpr *E);
+    void VisitInitListExpr(InitListExpr *E);
+    void VisitDesignatedInitExpr(DesignatedInitExpr *E);
+    void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+    void VisitVAArgExpr(VAArgExpr *E);
+    void VisitAddrLabelExpr(AddrLabelExpr *E);
+    void VisitStmtExpr(StmtExpr *E);
+    void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
+    void VisitChooseExpr(ChooseExpr *E);
+    void VisitGNUNullExpr(GNUNullExpr *E);
+    void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+    void VisitBlockExpr(BlockExpr *E);
+    void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
+
+    // Objective-C Expressions
+    void VisitObjCStringLiteral(ObjCStringLiteral *E);
+    void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+    void VisitObjCSelectorExpr(ObjCSelectorExpr *E);
+    void VisitObjCProtocolExpr(ObjCProtocolExpr *E);
+    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
+    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
+    void VisitObjCImplicitSetterGetterRefExpr(
+                        ObjCImplicitSetterGetterRefExpr *E);
+    void VisitObjCMessageExpr(ObjCMessageExpr *E);
+    void VisitObjCSuperExpr(ObjCSuperExpr *E);
+    void VisitObjCIsaExpr(ObjCIsaExpr *E);
+
+    // Objective-C Statements
+    void VisitObjCForCollectionStmt(ObjCForCollectionStmt *);
+    void VisitObjCAtCatchStmt(ObjCAtCatchStmt *);
+    void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *);
+    void VisitObjCAtTryStmt(ObjCAtTryStmt *);
+    void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
+    void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
+
+    // C++ Statements
+    void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+    void VisitCXXConstructExpr(CXXConstructExpr *E);
+    void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+    void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
+    void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
+    void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
+    void VisitCXXConstCastExpr(CXXConstCastExpr *E);
+    void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
+    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+    void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+  };
+}
+
+void PCHStmtWriter::VisitStmt(Stmt *S) {
+}
+
+void PCHStmtWriter::VisitNullStmt(NullStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getSemiLoc(), Record);
+  Code = pch::STMT_NULL;
+}
+
+void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
+  VisitStmt(S);
+  Record.push_back(S->size());
+  for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
+       CS != CSEnd; ++CS)
+    Writer.WriteSubStmt(*CS);
+  Writer.AddSourceLocation(S->getLBracLoc(), Record);
+  Writer.AddSourceLocation(S->getRBracLoc(), Record);
+  Code = pch::STMT_COMPOUND;
+}
+
+void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) {
+  VisitStmt(S);
+  Record.push_back(Writer.RecordSwitchCaseID(S));
+}
+
+void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
+  VisitSwitchCase(S);
+  Writer.WriteSubStmt(S->getLHS());
+  Writer.WriteSubStmt(S->getRHS());
+  Writer.WriteSubStmt(S->getSubStmt());
+  Writer.AddSourceLocation(S->getCaseLoc(), Record);
+  Writer.AddSourceLocation(S->getEllipsisLoc(), Record);
+  Writer.AddSourceLocation(S->getColonLoc(), Record);
+  Code = pch::STMT_CASE;
+}
+
+void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
+  VisitSwitchCase(S);
+  Writer.WriteSubStmt(S->getSubStmt());
+  Writer.AddSourceLocation(S->getDefaultLoc(), Record);
+  Writer.AddSourceLocation(S->getColonLoc(), Record);
+  Code = pch::STMT_DEFAULT;
+}
+
+void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) {
+  VisitStmt(S);
+  Writer.AddIdentifierRef(S->getID(), Record);
+  Writer.WriteSubStmt(S->getSubStmt());
+  Writer.AddSourceLocation(S->getIdentLoc(), Record);
+  Record.push_back(Writer.GetLabelID(S));
+  Code = pch::STMT_LABEL;
+}
+
+void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
+  VisitStmt(S);
+  Writer.AddDeclRef(S->getConditionVariable(), Record);
+  Writer.WriteSubStmt(S->getCond());
+  Writer.WriteSubStmt(S->getThen());
+  Writer.WriteSubStmt(S->getElse());
+  Writer.AddSourceLocation(S->getIfLoc(), Record);
+  Writer.AddSourceLocation(S->getElseLoc(), Record);
+  Code = pch::STMT_IF;
+}
+
+void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
+  VisitStmt(S);
+  Writer.AddDeclRef(S->getConditionVariable(), Record);
+  Writer.WriteSubStmt(S->getCond());
+  Writer.WriteSubStmt(S->getBody());
+  Writer.AddSourceLocation(S->getSwitchLoc(), Record);
+  for (SwitchCase *SC = S->getSwitchCaseList(); SC;
+       SC = SC->getNextSwitchCase())
+    Record.push_back(Writer.getSwitchCaseID(SC));
+  Code = pch::STMT_SWITCH;
+}
+
+void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) {
+  VisitStmt(S);
+  Writer.AddDeclRef(S->getConditionVariable(), Record);
+  Writer.WriteSubStmt(S->getCond());
+  Writer.WriteSubStmt(S->getBody());
+  Writer.AddSourceLocation(S->getWhileLoc(), Record);
+  Code = pch::STMT_WHILE;
+}
+
+void PCHStmtWriter::VisitDoStmt(DoStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getCond());
+  Writer.WriteSubStmt(S->getBody());
+  Writer.AddSourceLocation(S->getDoLoc(), Record);
+  Writer.AddSourceLocation(S->getWhileLoc(), Record);
+  Writer.AddSourceLocation(S->getRParenLoc(), Record);
+  Code = pch::STMT_DO;
+}
+
+void PCHStmtWriter::VisitForStmt(ForStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getInit());
+  Writer.WriteSubStmt(S->getCond());
+  Writer.AddDeclRef(S->getConditionVariable(), Record);
+  Writer.WriteSubStmt(S->getInc());
+  Writer.WriteSubStmt(S->getBody());
+  Writer.AddSourceLocation(S->getForLoc(), Record);
+  Writer.AddSourceLocation(S->getLParenLoc(), Record);
+  Writer.AddSourceLocation(S->getRParenLoc(), Record);
+  Code = pch::STMT_FOR;
+}
+
+void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) {
+  VisitStmt(S);
+  Record.push_back(Writer.GetLabelID(S->getLabel()));
+  Writer.AddSourceLocation(S->getGotoLoc(), Record);
+  Writer.AddSourceLocation(S->getLabelLoc(), Record);
+  Code = pch::STMT_GOTO;
+}
+
+void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getGotoLoc(), Record);
+  Writer.AddSourceLocation(S->getStarLoc(), Record);
+  Writer.WriteSubStmt(S->getTarget());
+  Code = pch::STMT_INDIRECT_GOTO;
+}
+
+void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getContinueLoc(), Record);
+  Code = pch::STMT_CONTINUE;
+}
+
+void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getBreakLoc(), Record);
+  Code = pch::STMT_BREAK;
+}
+
+void PCHStmtWriter::VisitReturnStmt(ReturnStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getRetValue());
+  Writer.AddSourceLocation(S->getReturnLoc(), Record);
+  Code = pch::STMT_RETURN;
+}
+
+void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) {
+  VisitStmt(S);
+  Writer.AddSourceLocation(S->getStartLoc(), Record);
+  Writer.AddSourceLocation(S->getEndLoc(), Record);
+  DeclGroupRef DG = S->getDeclGroup();
+  for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D)
+    Writer.AddDeclRef(*D, Record);
+  Code = pch::STMT_DECL;
+}
+
+void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) {
+  VisitStmt(S);
+  Record.push_back(S->getNumOutputs());
+  Record.push_back(S->getNumInputs());
+  Record.push_back(S->getNumClobbers());
+  Writer.AddSourceLocation(S->getAsmLoc(), Record);
+  Writer.AddSourceLocation(S->getRParenLoc(), Record);
+  Record.push_back(S->isVolatile());
+  Record.push_back(S->isSimple());
+  Record.push_back(S->isMSAsm());
+  Writer.WriteSubStmt(S->getAsmString());
+
+  // Outputs
+  for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {      
+    Writer.AddIdentifierRef(S->getOutputIdentifier(I), Record);
+    Writer.WriteSubStmt(S->getOutputConstraintLiteral(I));
+    Writer.WriteSubStmt(S->getOutputExpr(I));
+  }
+
+  // Inputs
+  for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
+    Writer.AddIdentifierRef(S->getInputIdentifier(I), Record);
+    Writer.WriteSubStmt(S->getInputConstraintLiteral(I));
+    Writer.WriteSubStmt(S->getInputExpr(I));
+  }
+
+  // Clobbers
+  for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
+    Writer.WriteSubStmt(S->getClobber(I));
+
+  Code = pch::STMT_ASM;
+}
+
+void PCHStmtWriter::VisitExpr(Expr *E) {
+  VisitStmt(E);
+  Writer.AddTypeRef(E->getType(), Record);
+  Record.push_back(E->isTypeDependent());
+  Record.push_back(E->isValueDependent());
+}
+
+void PCHStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Record.push_back(E->getIdentType()); // FIXME: stable encoding
+  Code = pch::EXPR_PREDEFINED;
+}
+
+void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getDecl(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  // FIXME: write qualifier
+  // FIXME: write explicit template arguments
+  Code = pch::EXPR_DECL_REF;
+}
+
+void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Writer.AddAPInt(E->getValue(), Record);
+  Code = pch::EXPR_INTEGER_LITERAL;
+}
+
+void PCHStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
+  VisitExpr(E);
+  Writer.AddAPFloat(E->getValue(), Record);
+  Record.push_back(E->isExact());
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Code = pch::EXPR_FLOATING_LITERAL;
+}
+
+void PCHStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getSubExpr());
+  Code = pch::EXPR_IMAGINARY_LITERAL;
+}
+
+void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) {
+  VisitExpr(E);
+  Record.push_back(E->getByteLength());
+  Record.push_back(E->getNumConcatenated());
+  Record.push_back(E->isWide());
+  // FIXME: String data should be stored as a blob at the end of the
+  // StringLiteral. However, we can't do so now because we have no
+  // provision for coping with abbreviations when we're jumping around
+  // the PCH file during deserialization.
+  Record.insert(Record.end(),
+                E->getStrData(), E->getStrData() + E->getByteLength());
+  for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
+    Writer.AddSourceLocation(E->getStrTokenLoc(I), Record);
+  Code = pch::EXPR_STRING_LITERAL;
+}
+
+void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
+  VisitExpr(E);
+  Record.push_back(E->getValue());
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Record.push_back(E->isWide());
+  Code = pch::EXPR_CHARACTER_LITERAL;
+}
+
+void PCHStmtWriter::VisitParenExpr(ParenExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLParen(), Record);
+  Writer.AddSourceLocation(E->getRParen(), Record);
+  Writer.WriteSubStmt(E->getSubExpr());
+  Code = pch::EXPR_PAREN;
+}
+
+void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getSubExpr());
+  Record.push_back(E->getOpcode()); // FIXME: stable encoding
+  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+  Code = pch::EXPR_UNARY_OPERATOR;
+}
+
+void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->isSizeOf());
+  if (E->isArgumentType())
+    Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record);
+  else {
+    Record.push_back(0);
+    Writer.WriteSubStmt(E->getArgumentExpr());
+  }
+  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_SIZEOF_ALIGN_OF;
+}
+
+void PCHStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getLHS());
+  Writer.WriteSubStmt(E->getRHS());
+  Writer.AddSourceLocation(E->getRBracketLoc(), Record);
+  Code = pch::EXPR_ARRAY_SUBSCRIPT;
+}
+
+void PCHStmtWriter::VisitCallExpr(CallExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumArgs());
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Writer.WriteSubStmt(E->getCallee());
+  for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg)
+    Writer.WriteSubStmt(*Arg);
+  Code = pch::EXPR_CALL;
+}
+
+void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getBase());
+  Writer.AddDeclRef(E->getMemberDecl(), Record);
+  Writer.AddSourceLocation(E->getMemberLoc(), Record);
+  Record.push_back(E->isArrow());
+  // FIXME: C++ nested-name-specifier
+  // FIXME: C++ template argument list
+  Code = pch::EXPR_MEMBER;
+}
+
+void PCHStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getBase());
+  Writer.AddSourceLocation(E->getIsaMemberLoc(), Record);
+  Record.push_back(E->isArrow());
+  Code = pch::EXPR_OBJC_ISA;
+}
+
+void PCHStmtWriter::VisitCastExpr(CastExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getSubExpr());
+  Record.push_back(E->getCastKind()); // FIXME: stable encoding
+}
+
+void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getLHS());
+  Writer.WriteSubStmt(E->getRHS());
+  Record.push_back(E->getOpcode()); // FIXME: stable encoding
+  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+  Code = pch::EXPR_BINARY_OPERATOR;
+}
+
+void PCHStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+  VisitBinaryOperator(E);
+  Writer.AddTypeRef(E->getComputationLHSType(), Record);
+  Writer.AddTypeRef(E->getComputationResultType(), Record);
+  Code = pch::EXPR_COMPOUND_ASSIGN_OPERATOR;
+}
+
+void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getCond());
+  Writer.WriteSubStmt(E->getLHS());
+  Writer.WriteSubStmt(E->getRHS());
+  Writer.AddSourceLocation(E->getQuestionLoc(), Record);
+  Writer.AddSourceLocation(E->getColonLoc(), Record);
+  Code = pch::EXPR_CONDITIONAL_OPERATOR;
+}
+
+void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+  VisitCastExpr(E);
+  Record.push_back(E->isLvalueCast());
+  Code = pch::EXPR_IMPLICIT_CAST;
+}
+
+void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+  VisitCastExpr(E);
+  Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record);
+}
+
+void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+  VisitExplicitCastExpr(E);
+  Writer.AddSourceLocation(E->getLParenLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_CSTYLE_CAST;
+}
+
+void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLParenLoc(), Record);
+  Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
+  Writer.WriteSubStmt(E->getInitializer());
+  Record.push_back(E->isFileScope());
+  Code = pch::EXPR_COMPOUND_LITERAL;
+}
+
+void PCHStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getBase());
+  Writer.AddIdentifierRef(&E->getAccessor(), Record);
+  Writer.AddSourceLocation(E->getAccessorLoc(), Record);
+  Code = pch::EXPR_EXT_VECTOR_ELEMENT;
+}
+
+void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumInits());
+  for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
+    Writer.WriteSubStmt(E->getInit(I));
+  Writer.WriteSubStmt(E->getSyntacticForm());
+  Writer.AddSourceLocation(E->getLBraceLoc(), Record);
+  Writer.AddSourceLocation(E->getRBraceLoc(), Record);
+  Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record);
+  Record.push_back(E->hadArrayRangeDesignator());
+  Code = pch::EXPR_INIT_LIST;
+}
+
+void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumSubExprs());
+  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
+    Writer.WriteSubStmt(E->getSubExpr(I));
+  Writer.AddSourceLocation(E->getEqualOrColonLoc(), Record);
+  Record.push_back(E->usesGNUSyntax());
+  for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
+                                             DEnd = E->designators_end();
+       D != DEnd; ++D) {
+    if (D->isFieldDesignator()) {
+      if (FieldDecl *Field = D->getField()) {
+        Record.push_back(pch::DESIG_FIELD_DECL);
+        Writer.AddDeclRef(Field, Record);
+      } else {
+        Record.push_back(pch::DESIG_FIELD_NAME);
+        Writer.AddIdentifierRef(D->getFieldName(), Record);
+      }
+      Writer.AddSourceLocation(D->getDotLoc(), Record);
+      Writer.AddSourceLocation(D->getFieldLoc(), Record);
+    } else if (D->isArrayDesignator()) {
+      Record.push_back(pch::DESIG_ARRAY);
+      Record.push_back(D->getFirstExprIndex());
+      Writer.AddSourceLocation(D->getLBracketLoc(), Record);
+      Writer.AddSourceLocation(D->getRBracketLoc(), Record);
+    } else {
+      assert(D->isArrayRangeDesignator() && "Unknown designator");
+      Record.push_back(pch::DESIG_ARRAY_RANGE);
+      Record.push_back(D->getFirstExprIndex());
+      Writer.AddSourceLocation(D->getLBracketLoc(), Record);
+      Writer.AddSourceLocation(D->getEllipsisLoc(), Record);
+      Writer.AddSourceLocation(D->getRBracketLoc(), Record);
+    }
+  }
+  Code = pch::EXPR_DESIGNATED_INIT;
+}
+
+void PCHStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+  VisitExpr(E);
+  Code = pch::EXPR_IMPLICIT_VALUE_INIT;
+}
+
+void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getSubExpr());
+  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_VA_ARG;
+}
+
+void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
+  Writer.AddSourceLocation(E->getLabelLoc(), Record);
+  Record.push_back(Writer.GetLabelID(E->getLabel()));
+  Code = pch::EXPR_ADDR_LABEL;
+}
+
+void PCHStmtWriter::VisitStmtExpr(StmtExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getSubStmt());
+  Writer.AddSourceLocation(E->getLParenLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_STMT;
+}
+
+void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
+  VisitExpr(E);
+  Writer.AddTypeRef(E->getArgType1(), Record);
+  Writer.AddTypeRef(E->getArgType2(), Record);
+  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_TYPES_COMPATIBLE;
+}
+
+void PCHStmtWriter::VisitChooseExpr(ChooseExpr *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getCond());
+  Writer.WriteSubStmt(E->getLHS());
+  Writer.WriteSubStmt(E->getRHS());
+  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_CHOOSE;
+}
+
+void PCHStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getTokenLocation(), Record);
+  Code = pch::EXPR_GNU_NULL;
+}
+
+void PCHStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumSubExprs());
+  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
+    Writer.WriteSubStmt(E->getExpr(I));
+  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_SHUFFLE_VECTOR;
+}
+
+void PCHStmtWriter::VisitBlockExpr(BlockExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getBlockDecl(), Record);
+  Record.push_back(E->hasBlockDeclRefExprs());
+  Code = pch::EXPR_BLOCK;
+}
+
+void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getDecl(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Record.push_back(E->isByRef());
+  Record.push_back(E->isConstQualAdded());
+  Code = pch::EXPR_BLOCK_DECL_REF;
+}
+
+//===----------------------------------------------------------------------===//
+// Objective-C Expressions and Statements.
+//===----------------------------------------------------------------------===//
+
+void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) {
+  VisitExpr(E);
+  Writer.WriteSubStmt(E->getString());
+  Writer.AddSourceLocation(E->getAtLoc(), Record);
+  Code = pch::EXPR_OBJC_STRING_LITERAL;
+}
+
+void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+  VisitExpr(E);
+  Writer.AddTypeRef(E->getEncodedType(), Record);
+  Writer.AddSourceLocation(E->getAtLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_OBJC_ENCODE;
+}
+
+void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+  VisitExpr(E);
+  Writer.AddSelectorRef(E->getSelector(), Record);
+  Writer.AddSourceLocation(E->getAtLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_OBJC_SELECTOR_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getProtocol(), Record);
+  Writer.AddSourceLocation(E->getAtLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_OBJC_PROTOCOL_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getDecl(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Writer.WriteSubStmt(E->getBase());
+  Record.push_back(E->isArrow());
+  Record.push_back(E->isFreeIvar());
+  Code = pch::EXPR_OBJC_IVAR_REF_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getProperty(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Writer.WriteSubStmt(E->getBase());
+  Code = pch::EXPR_OBJC_PROPERTY_REF_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr(
+                                  ObjCImplicitSetterGetterRefExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getGetterMethod(), Record);
+  Writer.AddDeclRef(E->getSetterMethod(), Record);
+
+  // NOTE: InterfaceDecl and Base are mutually exclusive.
+  Writer.AddDeclRef(E->getInterfaceDecl(), Record);
+  Writer.WriteSubStmt(E->getBase());
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Writer.AddSourceLocation(E->getClassLoc(), Record);
+  Code = pch::EXPR_OBJC_KVC_REF_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getNumArgs());
+  Writer.AddSourceLocation(E->getLeftLoc(), Record);
+  Writer.AddSourceLocation(E->getRightLoc(), Record);
+  Writer.AddSelectorRef(E->getSelector(), Record);
+  Writer.AddDeclRef(E->getMethodDecl(), Record); // optional
+  Writer.WriteSubStmt(E->getReceiver());
+
+  if (!E->getReceiver()) {
+    ObjCMessageExpr::ClassInfo CI = E->getClassInfo();
+    Writer.AddDeclRef(CI.first, Record);
+    Writer.AddIdentifierRef(CI.second, Record);
+  }
+
+  for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg)
+    Writer.WriteSubStmt(*Arg);
+  Code = pch::EXPR_OBJC_MESSAGE_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCSuperExpr(ObjCSuperExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLoc(), Record);
+  Code = pch::EXPR_OBJC_SUPER_EXPR;
+}
+
+void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+  VisitStmt(S);
+  Writer.WriteSubStmt(S->getElement());
+  Writer.WriteSubStmt(S->getCollection());
+  Writer.WriteSubStmt(S->getBody());
+  Writer.AddSourceLocation(S->getForLoc(), Record);
+  Writer.AddSourceLocation(S->getRParenLoc(), Record);
+  Code = pch::STMT_OBJC_FOR_COLLECTION;
+}
+
+void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+  Writer.WriteSubStmt(S->getCatchBody());
+  Writer.WriteSubStmt(S->getNextCatchStmt());
+  Writer.AddDeclRef(S->getCatchParamDecl(), Record);
+  Writer.AddSourceLocation(S->getAtCatchLoc(), Record);
+  Writer.AddSourceLocation(S->getRParenLoc(), Record);
+  Code = pch::STMT_OBJC_CATCH;
+}
+
+void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+  Writer.WriteSubStmt(S->getFinallyBody());
+  Writer.AddSourceLocation(S->getAtFinallyLoc(), Record);
+  Code = pch::STMT_OBJC_FINALLY;
+}
+
+void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+  Writer.WriteSubStmt(S->getTryBody());
+  Writer.WriteSubStmt(S->getCatchStmts());
+  Writer.WriteSubStmt(S->getFinallyStmt());
+  Writer.AddSourceLocation(S->getAtTryLoc(), Record);
+  Code = pch::STMT_OBJC_AT_TRY;
+}
+
+void PCHStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+  Writer.WriteSubStmt(S->getSynchExpr());
+  Writer.WriteSubStmt(S->getSynchBody());
+  Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record);
+  Code = pch::STMT_OBJC_AT_SYNCHRONIZED;
+}
+
+void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+  Writer.WriteSubStmt(S->getThrowExpr());
+  Writer.AddSourceLocation(S->getThrowLoc(), Record);
+  Code = pch::STMT_OBJC_AT_THROW;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions and Statements.
+//===----------------------------------------------------------------------===//
+
+void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  VisitCallExpr(E);
+  Record.push_back(E->getOperator());
+  Code = pch::EXPR_CXX_OPERATOR_CALL;
+}
+
+void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+  VisitExpr(E);
+  Writer.AddDeclRef(E->getConstructor(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Record.push_back(E->isElidable());
+  Record.push_back(E->requiresZeroInitialization());
+  Record.push_back(E->getNumArgs());
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+    Writer.WriteSubStmt(E->getArg(I));
+  Code = pch::EXPR_CXX_CONSTRUCT;
+}
+
+void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+  VisitExplicitCastExpr(E);
+  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+}
+
+void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+  VisitCXXNamedCastExpr(E);
+  Code = pch::EXPR_CXX_STATIC_CAST;
+}
+
+void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+  VisitCXXNamedCastExpr(E);
+  Code = pch::EXPR_CXX_DYNAMIC_CAST;
+}
+
+void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+  VisitCXXNamedCastExpr(E);
+  Code = pch::EXPR_CXX_REINTERPRET_CAST;
+}
+
+void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+  VisitCXXNamedCastExpr(E);
+  Code = pch::EXPR_CXX_CONST_CAST;
+}
+
+void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+  VisitExplicitCastExpr(E);
+  Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
+  Writer.AddSourceLocation(E->getRParenLoc(), Record);
+  Code = pch::EXPR_CXX_FUNCTIONAL_CAST;
+}
+
+void PCHStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->getValue());
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Code = pch::EXPR_CXX_BOOL_LITERAL;
+}
+
+void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLocation(), Record);
+  Code = pch::EXPR_CXX_NULL_PTR_LITERAL;
+}
+
+//===----------------------------------------------------------------------===//
+// PCHWriter Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
+  assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() &&
+         "SwitchCase recorded twice");
+  unsigned NextID = SwitchCaseIDs.size();
+  SwitchCaseIDs[S] = NextID;
+  return NextID;
+}
+
+unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
+  assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() &&
+         "SwitchCase hasn't been seen yet");
+  return SwitchCaseIDs[S];
+}
+
+/// \brief Retrieve the ID for the given label statement, which may
+/// or may not have been emitted yet.
+unsigned PCHWriter::GetLabelID(LabelStmt *S) {
+  std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S);
+  if (Pos != LabelIDs.end())
+    return Pos->second;
+
+  unsigned NextID = LabelIDs.size();
+  LabelIDs[S] = NextID;
+  return NextID;
+}
+
+/// \brief Write the given substatement or subexpression to the
+/// bitstream.
+void PCHWriter::WriteSubStmt(Stmt *S) {
+  RecordData Record;
+  PCHStmtWriter Writer(*this, Record);
+  ++NumStatements;
+
+  if (!S) {
+    Stream.EmitRecord(pch::STMT_NULL_PTR, Record);
+    return;
+  }
+
+  Writer.Code = pch::STMT_NULL_PTR;
+  Writer.Visit(S);
+  assert(Writer.Code != pch::STMT_NULL_PTR &&
+         "Unhandled expression writing PCH file");
+  Stream.EmitRecord(Writer.Code, Record);
+}
+
+/// \brief Flush all of the statements that have been added to the
+/// queue via AddStmt().
+void PCHWriter::FlushStmts() {
+  RecordData Record;
+  PCHStmtWriter Writer(*this, Record);
+
+  for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
+    ++NumStatements;
+    Stmt *S = StmtsToEmit[I];
+
+    if (!S) {
+      Stream.EmitRecord(pch::STMT_NULL_PTR, Record);
+      continue;
+    }
+
+    Writer.Code = pch::STMT_NULL_PTR;
+    Writer.Visit(S);
+    assert(Writer.Code != pch::STMT_NULL_PTR &&
+           "Unhandled expression writing PCH file");
+    Stream.EmitRecord(Writer.Code, Record);
+
+    assert(N == StmtsToEmit.size() &&
+           "Substatement writen via AddStmt rather than WriteSubStmt!");
+
+    // Note that we are at the end of a full expression. Any
+    // expression records that follow this one are part of a different
+    // expression.
+    Record.clear();
+    Stream.EmitRecord(pch::STMT_STOP, Record);
+  }
+
+  StmtsToEmit.clear();
+}
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
new file mode 100644
index 0000000..5706a07
--- /dev/null
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -0,0 +1,471 @@
+//===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- 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 PlistDiagnostics object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Checker/BugReporter/PathDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+using llvm::cast;
+
+typedef llvm::DenseMap<FileID, unsigned> FIDMap;
+
+namespace clang {
+  class Preprocessor;
+}
+
+namespace {
+struct CompareDiagnostics {
+  // Compare if 'X' is "<" than 'Y'.
+  bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
+    // First compare by location
+    const FullSourceLoc &XLoc = X->getLocation().asLocation();
+    const FullSourceLoc &YLoc = Y->getLocation().asLocation();
+    if (XLoc < YLoc)
+      return true;
+    if (XLoc != YLoc)
+      return false;
+    
+    // Next, compare by bug type.
+    llvm::StringRef XBugType = X->getBugType();
+    llvm::StringRef YBugType = Y->getBugType();
+    if (XBugType < YBugType)
+      return true;
+    if (XBugType != YBugType)
+      return false;
+    
+    // Next, compare by bug description.
+    llvm::StringRef XDesc = X->getDescription();
+    llvm::StringRef YDesc = Y->getDescription();
+    if (XDesc < YDesc)
+      return true;
+    if (XDesc != YDesc)
+      return false;
+    
+    // FIXME: Further refine by comparing PathDiagnosticPieces?
+    return false;    
+  }  
+};  
+}
+
+namespace {
+  class PlistDiagnostics : public PathDiagnosticClient {
+    std::vector<const PathDiagnostic*> BatchedDiags;
+    const std::string OutputFile;
+    const LangOptions &LangOpts;
+    llvm::OwningPtr<PathDiagnosticClient> SubPD;
+    bool flushed;
+  public:
+    PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
+                     PathDiagnosticClient *subPD);
+
+    ~PlistDiagnostics() { FlushDiagnostics(NULL); }
+
+    void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
+    
+    void HandlePathDiagnostic(const PathDiagnostic* D);
+    
+    virtual llvm::StringRef getName() const {
+      return "PlistDiagnostics";
+    }
+
+    PathGenerationScheme getGenerationScheme() const;
+    bool supportsLogicalOpControlFlow() const { return true; }
+    bool supportsAllBlockEdges() const { return true; }
+    virtual bool useVerboseDescription() const { return false; }
+  };
+} // end anonymous namespace
+
+PlistDiagnostics::PlistDiagnostics(const std::string& output,
+                                   const LangOptions &LO,
+                                   PathDiagnosticClient *subPD)
+  : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}
+
+PathDiagnosticClient*
+clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
+                                   PathDiagnosticClient *subPD) {
+  return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
+}
+
+PathDiagnosticClient::PathGenerationScheme
+PlistDiagnostics::getGenerationScheme() const {
+  if (const PathDiagnosticClient *PD = SubPD.get())
+    return PD->getGenerationScheme();
+
+  return Extensive;
+}
+
+static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
+                   const SourceManager* SM, SourceLocation L) {
+
+  FileID FID = SM->getFileID(SM->getInstantiationLoc(L));
+  FIDMap::iterator I = FIDs.find(FID);
+  if (I != FIDs.end()) return;
+  FIDs[FID] = V.size();
+  V.push_back(FID);
+}
+
+static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
+                       SourceLocation L) {
+  FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
+  FIDMap::const_iterator I = FIDs.find(FID);
+  assert(I != FIDs.end());
+  return I->second;
+}
+
+static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
+  for (unsigned i = 0; i < indent; ++i) o << ' ';
+  return o;
+}
+
+static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
+                         const LangOptions &LangOpts,
+                         SourceLocation L, const FIDMap &FM,
+                         unsigned indent, bool extend = false) {
+
+  FullSourceLoc Loc(SM.getInstantiationLoc(L), const_cast<SourceManager&>(SM));
+
+  // Add in the length of the token, so that we cover multi-char tokens.
+  unsigned offset =
+    extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
+
+  Indent(o, indent) << "<dict>\n";
+  Indent(o, indent) << " <key>line</key><integer>"
+                    << Loc.getInstantiationLineNumber() << "</integer>\n";
+  Indent(o, indent) << " <key>col</key><integer>"
+                    << Loc.getInstantiationColumnNumber() + offset << "</integer>\n";
+  Indent(o, indent) << " <key>file</key><integer>"
+                    << GetFID(FM, SM, Loc) << "</integer>\n";
+  Indent(o, indent) << "</dict>\n";
+}
+
+static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
+                         const LangOptions &LangOpts,
+                         const PathDiagnosticLocation &L, const FIDMap& FM,
+                         unsigned indent, bool extend = false) {
+  EmitLocation(o, SM, LangOpts, L.asLocation(), FM, indent, extend);
+}
+
+static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM,
+                      const LangOptions &LangOpts,
+                      PathDiagnosticRange R, const FIDMap &FM,
+                      unsigned indent) {
+  Indent(o, indent) << "<array>\n";
+  EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
+  EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint);
+  Indent(o, indent) << "</array>\n";
+}
+
+static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
+                                     const std::string& s) {
+  o << "<string>";
+  for (std::string::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
+    char c = *I;
+    switch (c) {
+    default:   o << c; break;
+    case '&':  o << "&amp;"; break;
+    case '<':  o << "&lt;"; break;
+    case '>':  o << "&gt;"; break;
+    case '\'': o << "&apos;"; break;
+    case '\"': o << "&quot;"; break;
+    }
+  }
+  o << "</string>";
+  return o;
+}
+
+static void ReportControlFlow(llvm::raw_ostream& o,
+                              const PathDiagnosticControlFlowPiece& P,
+                              const FIDMap& FM,
+                              const SourceManager &SM,
+                              const LangOptions &LangOpts,
+                              unsigned indent) {
+
+  Indent(o, indent) << "<dict>\n";
+  ++indent;
+
+  Indent(o, indent) << "<key>kind</key><string>control</string>\n";
+
+  // Emit edges.
+  Indent(o, indent) << "<key>edges</key>\n";
+  ++indent;
+  Indent(o, indent) << "<array>\n";
+  ++indent;
+  for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end();
+       I!=E; ++I) {
+    Indent(o, indent) << "<dict>\n";
+    ++indent;
+    Indent(o, indent) << "<key>start</key>\n";
+    EmitRange(o, SM, LangOpts, I->getStart().asRange(), FM, indent+1);
+    Indent(o, indent) << "<key>end</key>\n";
+    EmitRange(o, SM, LangOpts, I->getEnd().asRange(), FM, indent+1);
+    --indent;
+    Indent(o, indent) << "</dict>\n";
+  }
+  --indent;
+  Indent(o, indent) << "</array>\n";
+  --indent;
+
+  // Output any helper text.
+  const std::string& s = P.getString();
+  if (!s.empty()) {
+    Indent(o, indent) << "<key>alternate</key>";
+    EmitString(o, s) << '\n';
+  }
+
+  --indent;
+  Indent(o, indent) << "</dict>\n";
+}
+
+static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
+                        const FIDMap& FM,
+                        const SourceManager &SM,
+                        const LangOptions &LangOpts,
+                        unsigned indent) {
+
+  Indent(o, indent) << "<dict>\n";
+  ++indent;
+
+  Indent(o, indent) << "<key>kind</key><string>event</string>\n";
+
+  // Output the location.
+  FullSourceLoc L = P.getLocation().asLocation();
+
+  Indent(o, indent) << "<key>location</key>\n";
+  EmitLocation(o, SM, LangOpts, L, FM, indent);
+
+  // Output the ranges (if any).
+  PathDiagnosticPiece::range_iterator RI = P.ranges_begin(),
+  RE = P.ranges_end();
+
+  if (RI != RE) {
+    Indent(o, indent) << "<key>ranges</key>\n";
+    Indent(o, indent) << "<array>\n";
+    ++indent;
+    for (; RI != RE; ++RI)
+      EmitRange(o, SM, LangOpts, *RI, FM, indent+1);
+    --indent;
+    Indent(o, indent) << "</array>\n";
+  }
+
+  // Output the text.
+  assert(!P.getString().empty());
+  Indent(o, indent) << "<key>extended_message</key>\n";
+  Indent(o, indent);
+  EmitString(o, P.getString()) << '\n';
+
+  // Output the short text.
+  // FIXME: Really use a short string.
+  Indent(o, indent) << "<key>message</key>\n";
+  EmitString(o, P.getString()) << '\n';
+
+  // Finish up.
+  --indent;
+  Indent(o, indent); o << "</dict>\n";
+}
+
+static void ReportMacro(llvm::raw_ostream& o,
+                        const PathDiagnosticMacroPiece& P,
+                        const FIDMap& FM, const SourceManager &SM,
+                        const LangOptions &LangOpts,
+                        unsigned indent) {
+
+  for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
+       I!=E; ++I) {
+
+    switch ((*I)->getKind()) {
+    default:
+      break;
+    case PathDiagnosticPiece::Event:
+      ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
+                  indent);
+      break;
+    case PathDiagnosticPiece::Macro:
+      ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
+                  indent);
+      break;
+    }
+  }
+}
+
+static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
+                       const FIDMap& FM, const SourceManager &SM,
+                       const LangOptions &LangOpts) {
+
+  unsigned indent = 4;
+
+  switch (P.getKind()) {
+  case PathDiagnosticPiece::ControlFlow:
+    ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
+                      LangOpts, indent);
+    break;
+  case PathDiagnosticPiece::Event:
+    ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
+                indent);
+    break;
+  case PathDiagnosticPiece::Macro:
+    ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
+                indent);
+    break;
+  }
+}
+
+void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+  if (!D)
+    return;
+
+  if (D->empty()) {
+    delete D;
+    return;
+  }
+
+  // We need to flatten the locations (convert Stmt* to locations) because
+  // the referenced statements may be freed by the time the diagnostics
+  // are emitted.
+  const_cast<PathDiagnostic*>(D)->flattenLocations();
+  BatchedDiags.push_back(D);
+}
+
+void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
+                                        *FilesMade) {
+  
+  if (flushed)
+    return;
+  
+  flushed = true;
+  
+  // Sort the diagnostics so that they are always emitted in a deterministic
+  // order.
+  if (!BatchedDiags.empty())
+    std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics()); 
+
+  // Build up a set of FIDs that we use by scanning the locations and
+  // ranges of the diagnostics.
+  FIDMap FM;
+  llvm::SmallVector<FileID, 10> Fids;
+  const SourceManager* SM = 0;
+
+  if (!BatchedDiags.empty())
+    SM = &(*BatchedDiags.begin())->begin()->getLocation().getManager();
+
+  for (std::vector<const PathDiagnostic*>::iterator DI = BatchedDiags.begin(),
+       DE = BatchedDiags.end(); DI != DE; ++DI) {
+
+    const PathDiagnostic *D = *DI;
+
+    for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I!=E; ++I) {
+      AddFID(FM, Fids, SM, I->getLocation().asLocation());
+
+      for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
+           RE=I->ranges_end(); RI!=RE; ++RI) {
+        AddFID(FM, Fids, SM, RI->getBegin());
+        AddFID(FM, Fids, SM, RI->getEnd());
+      }
+    }
+  }
+
+  // Open the file.
+  std::string ErrMsg;
+  llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg);
+  if (!ErrMsg.empty()) {
+    llvm::errs() << "warning: could not creat file: " << OutputFile << '\n';
+    return;
+  }
+
+  // Write the plist header.
+  o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+  "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
+  "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+  "<plist version=\"1.0\">\n";
+
+  // Write the root object: a <dict> containing...
+  //  - "files", an <array> mapping from FIDs to file names
+  //  - "diagnostics", an <array> containing the path diagnostics
+  o << "<dict>\n"
+       " <key>files</key>\n"
+       " <array>\n";
+
+  for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
+       I!=E; ++I) {
+    o << "  ";
+    EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
+  }
+
+  o << " </array>\n"
+       " <key>diagnostics</key>\n"
+       " <array>\n";
+
+  for (std::vector<const PathDiagnostic*>::iterator DI=BatchedDiags.begin(),
+       DE = BatchedDiags.end(); DI!=DE; ++DI) {
+
+    o << "  <dict>\n"
+         "   <key>path</key>\n";
+
+    const PathDiagnostic *D = *DI;
+    // Create an owning smart pointer for 'D' just so that we auto-free it
+    // when we exit this method.
+    llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D));
+
+    o << "   <array>\n";
+
+    for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I)
+      ReportDiag(o, *I, FM, *SM, LangOpts);
+
+    o << "   </array>\n";
+
+    // Output the bug type and bug category.
+    o << "   <key>description</key>";
+    EmitString(o, D->getDescription()) << '\n';
+    o << "   <key>category</key>";
+    EmitString(o, D->getCategory()) << '\n';
+    o << "   <key>type</key>";
+    EmitString(o, D->getBugType()) << '\n';
+
+    // Output the location of the bug.
+    o << "  <key>location</key>\n";
+    EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
+
+    // Output the diagnostic to the sub-diagnostic client, if any.
+    if (SubPD) {
+      SubPD->HandlePathDiagnostic(OwnedD.take());
+      llvm::SmallVector<std::string, 1> SubFilesMade;
+      SubPD->FlushDiagnostics(SubFilesMade);
+
+      if (!SubFilesMade.empty()) {
+        o << "  <key>" << SubPD->getName() << "_files</key>\n";
+        o << "  <array>\n";
+        for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
+          o << "   <string>" << SubFilesMade[i] << "</string>\n";
+        o << "  </array>\n";
+      }
+    }
+
+    // Close up the entry.
+    o << "  </dict>\n";
+  }
+
+  o << " </array>\n";
+
+  // Finish.
+  o << "</dict>\n</plist>";
+  
+  if (FilesMade)
+    FilesMade->push_back(OutputFile);
+  
+  BatchedDiags.clear();
+}
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
new file mode 100644
index 0000000..8d64a64
--- /dev/null
+++ b/lib/Frontend/PrintParserCallbacks.cpp
@@ -0,0 +1,848 @@
+//===--- PrintParserActions.cpp - Implement -parse-print-callbacks mode ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code simply runs the preprocessor on the input file and prints out the
+// result.  This is the traditional behavior of the -E option.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Parse/Action.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+  class ParserPrintActions : public MinimalAction {
+  llvm::raw_ostream& Out;
+
+  public:
+    ParserPrintActions(Preprocessor &PP, llvm::raw_ostream& OS)
+      : MinimalAction(PP), Out(OS) {}
+
+    // Printing Functions which also must call MinimalAction
+
+    /// ActOnDeclarator - This callback is invoked when a declarator is parsed
+    /// and 'Init' specifies the initializer if any.  This is for things like:
+    /// "int X = 4" or "typedef int foo".
+    virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
+      Out << __FUNCTION__ << " ";
+      if (IdentifierInfo *II = D.getIdentifier()) {
+        Out << "'" << II->getName() << "'";
+      } else {
+        Out << "<anon>";
+      }
+      Out << "\n";
+
+      // Pass up to EmptyActions so that the symbol table is maintained right.
+      return MinimalAction::ActOnDeclarator(S, D);
+    }
+    /// ActOnPopScope - This callback is called immediately before the specified
+    /// scope is popped and deleted.
+    virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {
+      Out << __FUNCTION__ << "\n";
+      return MinimalAction::ActOnPopScope(Loc, S);
+    }
+
+    /// ActOnTranslationUnitScope - This callback is called once, immediately
+    /// after creating the translation unit scope (in Parser::Initialize).
+    virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+      Out << __FUNCTION__ << "\n";
+      MinimalAction::ActOnTranslationUnitScope(Loc, S);
+    }
+
+
+    Action::DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+                                               IdentifierInfo *ClassName,
+                                               SourceLocation ClassLoc,
+                                               IdentifierInfo *SuperName,
+                                               SourceLocation SuperLoc,
+                                               const DeclPtrTy *ProtoRefs,
+                                               unsigned NumProtocols,
+                                               const SourceLocation *ProtoLocs,
+                                               SourceLocation EndProtoLoc,
+                                               AttributeList *AttrList) {
+      Out << __FUNCTION__ << "\n";
+      return MinimalAction::ActOnStartClassInterface(AtInterfaceLoc,
+                                                     ClassName, ClassLoc,
+                                                     SuperName, SuperLoc,
+                                                     ProtoRefs, NumProtocols,
+                                                     ProtoLocs, EndProtoLoc,
+                                                     AttrList);
+    }
+
+    /// ActOnForwardClassDeclaration -
+    /// Scope will always be top level file scope.
+    Action::DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
+                                                   IdentifierInfo **IdentList,
+                                                   SourceLocation *IdentLocs,
+                                                   unsigned NumElts) {
+      Out << __FUNCTION__ << "\n";
+      return MinimalAction::ActOnForwardClassDeclaration(AtClassLoc, IdentList,
+                                                         IdentLocs, NumElts);
+    }
+
+    // Pure Printing
+
+    /// ActOnParamDeclarator - This callback is invoked when a parameter
+    /// declarator is parsed. This callback only occurs for functions
+    /// with prototypes. S is the function prototype scope for the
+    /// parameters (C++ [basic.scope.proto]).
+    virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) {
+      Out << __FUNCTION__ << " ";
+      if (IdentifierInfo *II = D.getIdentifier()) {
+        Out << "'" << II->getName() << "'";
+      } else {
+        Out << "<anon>";
+      }
+      Out << "\n";
+      return DeclPtrTy();
+    }
+
+    /// AddInitializerToDecl - This action is called immediately after
+    /// ParseDeclarator (when an initializer is present). The code is factored
+    /// this way to make sure we are able to handle the following:
+    ///   void func() { int xx = xx; }
+    /// This allows ActOnDeclarator to register "xx" prior to parsing the
+    /// initializer. The declaration above should still result in a warning,
+    /// since the reference to "xx" is uninitialized.
+    virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed,
+    /// this gives the actions implementation a chance to process the group as
+    /// a whole.
+    virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS,
+                                                   DeclPtrTy *Group,
+                                                   unsigned NumDecls) {
+      Out << __FUNCTION__ << "\n";
+      return DeclGroupPtrTy();
+    }
+
+    /// ActOnStartOfFunctionDef - This is called at the start of a function
+    /// definition, instead of calling ActOnDeclarator.  The Declarator includes
+    /// information about formal arguments that are part of this function.
+    virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope,
+                                              Declarator &D){
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    /// ActOnStartOfFunctionDef - This is called at the start of a function
+    /// definition, after the FunctionDecl has already been created.
+    virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    /// ActOnFunctionDefBody - This is called when a function body has completed
+    /// parsing.  Decl is the DeclTy returned by ParseStartOfFunctionDef.
+    virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc,
+                                            ExprArg AsmString) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+    /// no declarator (e.g. "struct foo;") is parsed.
+    virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    /// ActOnLinkageSpec - Parsed a C++ linkage-specification that
+    /// contained braces. Lang/StrSize contains the language string that
+    /// was parsed at location Loc. Decls/NumDecls provides the
+    /// declarations parsed inside the linkage specification.
+    virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc,
+                                       SourceLocation LBrace,
+                                       SourceLocation RBrace, const char *Lang,
+                                       unsigned StrSize,
+                                       DeclPtrTy *Decls, unsigned NumDecls) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    /// ActOnLinkageSpec - Parsed a C++ linkage-specification without
+    /// braces. Lang/StrSize contains the language string that was
+    /// parsed at location Loc. D is the declaration parsed.
+    virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
+                                       unsigned StrSize, DeclPtrTy D) {
+      return DeclPtrTy();
+    }
+
+    //===------------------------------------------------------------------===//
+    // Type Parsing Callbacks.
+    //===------------------------------------------------------------------===//
+
+    virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
+      Out << __FUNCTION__ << "\n";
+      return TypeResult();
+    }
+
+    virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                               SourceLocation KWLoc, const CXXScopeSpec &SS,
+                               IdentifierInfo *Name, SourceLocation NameLoc,
+                               AttributeList *Attr, AccessSpecifier AS,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               bool &OwnedDecl, bool &IsDependent) {
+      // TagType is an instance of DeclSpec::TST, indicating what kind of tag this
+      // is (struct/union/enum/class).
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    /// Act on @defs() element found when parsing a structure.  ClassName is the
+    /// name of the referenced class.
+    virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
+                           IdentifierInfo *ClassName,
+                           llvm::SmallVectorImpl<DeclPtrTy> &Decls) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
+                                 SourceLocation DeclStart,
+                                 Declarator &D, ExprTy *BitfieldWidth) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
+                                DeclPtrTy IntfDecl,
+                                Declarator &D, ExprTy *BitfieldWidth,
+                                tok::ObjCKeywordKind visibility) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl,
+                             DeclPtrTy *Fields, unsigned NumFields,
+                             SourceLocation LBrac, SourceLocation RBrac,
+                             AttributeList *AttrList) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
+                                        DeclPtrTy LastEnumConstant,
+                                        SourceLocation IdLoc,IdentifierInfo *Id,
+                                        SourceLocation EqualLoc, ExprTy *Val) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+                               SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
+                               DeclPtrTy *Elements, unsigned NumElements,
+                               Scope *S, AttributeList *AttrList) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    //===------------------------------------------------------------------===//
+    // Statement Parsing Callbacks.
+    //===------------------------------------------------------------------===//
+
+    virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L,
+                                               SourceLocation R,
+                                               MultiStmtArg Elts,
+                                               bool isStmtExpr) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+                                           SourceLocation StartLoc,
+                                           SourceLocation EndLoc) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) {
+      Out << __FUNCTION__ << "\n";
+      return OwningStmtResult(*this, Expr->release());
+    }
+
+    /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
+    /// which can specify an RHS value.
+    virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc,
+                                           ExprArg LHSVal,
+                                           SourceLocation DotDotDotLoc,
+                                           ExprArg RHSVal,
+                                           SourceLocation ColonLoc) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+                                              SourceLocation ColonLoc,
+                                              StmtArg SubStmt, Scope *CurScope){
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
+                                            IdentifierInfo *II,
+                                            SourceLocation ColonLoc,
+                                            StmtArg SubStmt) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
+                                         FullExprArg CondVal, DeclPtrTy CondVar,
+                                         StmtArg ThenVal,
+                                         SourceLocation ElseLoc,
+                                         StmtArg ElseVal) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, 
+                                                    DeclPtrTy CondVar) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+                                                   StmtArg Switch,
+                                                   StmtArg Body) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
+                                            FullExprArg Cond, DeclPtrTy CondVar,
+                                            StmtArg Body) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
+                                         SourceLocation WhileLoc,
+                                         SourceLocation LPLoc, ExprArg Cond,
+                                         SourceLocation RPLoc){
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
+                                        SourceLocation LParenLoc,
+                                        StmtArg First, FullExprArg Second,
+                                        DeclPtrTy SecondVar,
+                                        FullExprArg Third, 
+                                        SourceLocation RParenLoc,
+                                        StmtArg Body) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnObjCForCollectionStmt(
+                                       SourceLocation ForColLoc,
+                                       SourceLocation LParenLoc,
+                                       StmtArg First, ExprArg Second,
+                                       SourceLocation RParenLoc, StmtArg Body) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
+                                           SourceLocation LabelLoc,
+                                           IdentifierInfo *LabelII) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+                                                   SourceLocation StarLoc,
+                                                   ExprArg DestExp) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
+                                               Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
+                                            Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
+                                             ExprArg RetValExp) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+    virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
+                                          bool IsSimple,
+                                          bool IsVolatile,
+                                          unsigned NumOutputs,
+                                          unsigned NumInputs,
+                                          IdentifierInfo **Names,
+                                          MultiExprArg Constraints,
+                                          MultiExprArg Exprs,
+                                          ExprArg AsmString,
+                                          MultiExprArg Clobbers,
+                                          SourceLocation RParenLoc,
+                                          bool MSAsm) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    // Objective-c statements
+    virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
+                                                  SourceLocation RParen,
+                                                  DeclPtrTy Parm, StmtArg Body,
+                                                  StmtArg CatchList) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
+                                                    StmtArg Body) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
+                                                StmtArg Try, StmtArg Catch,
+                                                StmtArg Finally) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
+                                                  ExprArg Throw,
+                                                  Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+                                                         ExprArg SynchExpr,
+                                                         StmtArg SynchBody) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    // C++ Statements
+    virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+                                                DeclPtrTy ExceptionDecl,
+                                                StmtArg HandlerBlock) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+                                              StmtArg TryBlock,
+                                              MultiStmtArg Handlers) {
+      Out << __FUNCTION__ << "\n";
+      return StmtEmpty();
+    }
+
+    //===------------------------------------------------------------------===//
+    // Expression Parsing Callbacks.
+    //===------------------------------------------------------------------===//
+
+    // Primary Expressions.
+
+    /// ActOnIdentifierExpr - Parse an identifier in expression context.
+    /// 'HasTrailingLParen' indicates whether or not the identifier has a '('
+    /// token immediately after it.
+    virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
+                                                 IdentifierInfo &II,
+                                                 bool HasTrailingLParen,
+                                                 const CXXScopeSpec *SS,
+                                                 bool isAddressOfOperand) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
+                               Scope *S, SourceLocation OperatorLoc,
+                               OverloadedOperatorKind Op,
+                               bool HasTrailingLParen, const CXXScopeSpec &SS,
+                               bool isAddressOfOperand) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXConversionFunctionExpr(
+                               Scope *S, SourceLocation OperatorLoc,
+                               TypeTy *Type, bool HasTrailingLParen,
+                               const CXXScopeSpec &SS,bool isAddressOfOperand) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
+                                                 tok::TokenKind Kind) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCharacterConstant(const Token &) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnNumericConstant(const Token &) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+    /// fragments (e.g. "foo" "bar" L"baz").
+    virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
+                                                unsigned NumToks) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
+                                            ExprArg Val) {
+      Out << __FUNCTION__ << "\n";
+      return move(Val);  // Default impl returns operand.
+    }
+
+    // Postfix Expressions.
+    virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+                                                 tok::TokenKind Kind,
+                                                 ExprArg Input) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+    virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
+                                                     SourceLocation LLoc,
+                                                     ExprArg Idx,
+                                                     SourceLocation RLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+    virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
+                                                      SourceLocation OpLoc,
+                                                      tok::TokenKind OpKind,
+                                                      SourceLocation MemberLoc,
+                                                      IdentifierInfo &Member,
+                                                      DeclPtrTy ImplDecl,
+                                                      const CXXScopeSpec *SS=0) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
+                                           SourceLocation LParenLoc,
+                                           MultiExprArg Args,
+                                           SourceLocation *CommaLocs,
+                                           SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    // Unary Operators.  'Tok' is the token for the operator.
+    virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+                                          tok::TokenKind Op, ExprArg Input) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+    virtual OwningExprResult
+      ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+                             void *TyOrEx, const SourceRange &ArgRange) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen,
+                                                  TypeTy *Ty,
+                                                  SourceLocation RParen,
+                                                  ExprArg Op) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+    virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
+                                           MultiExprArg InitList,
+                                           SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+    virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+                                           TypeTy *Ty, SourceLocation RParenLoc,
+                                           ExprArg Op) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+                                        tok::TokenKind Kind,
+                                        ExprArg LHS, ExprArg RHS) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    /// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+    /// in the case of a the GNU conditional expr extension.
+    virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+                                                SourceLocation ColonLoc,
+                                                ExprArg Cond, ExprArg LHS,
+                                                ExprArg RHS) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    //===--------------------- GNU Extension Expressions ------------------===//
+
+    virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
+                                            SourceLocation LabLoc,
+                                            IdentifierInfo *LabelII) {// "&&foo"
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc,
+                                           StmtArg SubStmt,
+                                           SourceLocation RPLoc) { // "({..})"
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
+                                                  SourceLocation BuiltinLoc,
+                                                  SourceLocation TypeLoc,
+                                                  TypeTy *Arg1,
+                                                  OffsetOfComponent *CompPtr,
+                                                  unsigned NumComponents,
+                                                  SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    // __builtin_types_compatible_p(type1, type2)
+    virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+                                                      TypeTy *arg1,TypeTy *arg2,
+                                                      SourceLocation RPLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+    // __builtin_choose_expr(constExpr, expr1, expr2)
+    virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+                                             ExprArg cond, ExprArg expr1,
+                                             ExprArg expr2,
+                                             SourceLocation RPLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    // __builtin_va_arg(expr, type)
+    virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+                                  ExprArg expr, TypeTy *type,
+                                  SourceLocation RPLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
+                                                StmtArg Body,
+                                                Scope *CurScope) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                             IdentifierInfo *Ident,
+                                             SourceLocation LBrace,
+                                             AttributeList *AttrList) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) {
+      Out << __FUNCTION__ << "\n";
+      return;
+    }
+
+#if 0
+    // FIXME: AttrList should be deleted by this function, but the definition
+    // would have to be available.
+    virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
+                                          SourceLocation UsingLoc,
+                                          SourceLocation NamespcLoc,
+                                          const CXXScopeSpec &SS,
+                                          SourceLocation IdentLoc,
+                                          IdentifierInfo *NamespcName,
+                                          AttributeList *AttrList) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+#endif
+
+    virtual void ActOnParamDefaultArgument(DeclPtrTy param,
+                                           SourceLocation EqualLoc,
+                                           ExprArg defarg) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
+                                                   SourceLocation EqualLoc,
+                                                   SourceLocation ArgLoc) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
+                                               SourceLocation LParenLoc,
+                                               MultiExprArg Exprs,
+                                               SourceLocation *CommaLocs,
+                                               SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return;
+    }
+
+    virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
+                                                       DeclPtrTy Method) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
+                                                        DeclPtrTy Method) {
+      Out << __FUNCTION__ << "\n";
+    }
+
+    virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+                                                   ExprArg AssertExpr,
+                                                   ExprArg AssertMessageExpr) {
+      Out << __FUNCTION__ << "\n";
+      return DeclPtrTy();
+    }
+
+    virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+                                               tok::TokenKind Kind,
+                                               SourceLocation LAngleBracketLoc,
+                                               TypeTy *Ty,
+                                               SourceLocation RAngleBracketLoc,
+                                               SourceLocation LParenLoc,
+                                               ExprArg Op,
+                                               SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+                                            SourceLocation LParenLoc,
+                                            bool isType, void *TyOrExpr,
+                                            SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
+                                                 tok::TokenKind Kind) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
+                                                     TypeTy *TypeRep,
+                                                     SourceLocation LParenLoc,
+                                                     MultiExprArg Exprs,
+                                                     SourceLocation *CommaLocs,
+                                                     SourceLocation RParenLoc) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S,
+                                                        SourceLocation StartLoc,
+                                                        Declarator &D,
+                                                        SourceLocation EqualLoc,
+                                                        ExprArg AssignExprVal) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc,
+                                         bool UseGlobal,
+                                         SourceLocation PlacementLParen,
+                                         MultiExprArg PlacementArgs,
+                                         SourceLocation PlacementRParen,
+                                         bool ParenTypeId, Declarator &D,
+                                         SourceLocation ConstructorLParen,
+                                         MultiExprArg ConstructorArgs,
+                                         SourceLocation ConstructorRParen) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
+                                            bool UseGlobal, bool ArrayForm,
+                                            ExprArg Operand) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+
+    virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+                                                 SourceLocation KWLoc,
+                                                 SourceLocation LParen,
+                                                 TypeTy *Ty,
+                                                 SourceLocation RParen) {
+      Out << __FUNCTION__ << "\n";
+      return ExprEmpty();
+    }
+  };
+}
+
+MinimalAction *clang::CreatePrintParserActionsAction(Preprocessor &PP,
+                                                     llvm::raw_ostream* OS) {
+  return new ParserPrintActions(PP, *OS);
+}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
new file mode 100644
index 0000000..43deaee
--- /dev/null
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -0,0 +1,519 @@
+//===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code simply runs the preprocessor on the input file and prints out the
+// result.  This is the traditional behavior of the -E option.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Pragma.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/TokenConcatenation.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+using namespace clang;
+
+/// PrintMacroDefinition - Print a macro definition in a form that will be
+/// properly accepted back as a definition.
+static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
+                                 Preprocessor &PP, llvm::raw_ostream &OS) {
+  OS << "#define " << II.getName();
+
+  if (MI.isFunctionLike()) {
+    OS << '(';
+    if (!MI.arg_empty()) {
+      MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
+      for (; AI+1 != E; ++AI) {
+        OS << (*AI)->getName();
+        OS << ',';
+      }
+
+      // Last argument.
+      if ((*AI)->getName() == "__VA_ARGS__")
+        OS << "...";
+      else
+        OS << (*AI)->getName();
+    }
+
+    if (MI.isGNUVarargs())
+      OS << "...";  // #define foo(x...)
+    
+    OS << ')';
+  }
+
+  // GCC always emits a space, even if the macro body is empty.  However, do not
+  // want to emit two spaces if the first token has a leading space.
+  if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
+    OS << ' ';
+
+  llvm::SmallVector<char, 128> SpellingBuffer;
+  for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
+       I != E; ++I) {
+    if (I->hasLeadingSpace())
+      OS << ' ';
+
+    // Make sure we have enough space in the spelling buffer.
+    if (I->getLength() > SpellingBuffer.size())
+      SpellingBuffer.resize(I->getLength());
+    const char *Buffer = SpellingBuffer.data();
+    unsigned SpellingLen = PP.getSpelling(*I, Buffer);
+    OS.write(Buffer, SpellingLen);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessed token printer
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PrintPPOutputPPCallbacks : public PPCallbacks {
+  Preprocessor &PP;
+  TokenConcatenation ConcatInfo;
+public:
+  llvm::raw_ostream &OS;
+private:
+  unsigned CurLine;
+  bool EmittedTokensOnThisLine;
+  bool EmittedMacroOnThisLine;
+  SrcMgr::CharacteristicKind FileType;
+  llvm::SmallString<512> CurFilename;
+  bool Initialized;
+  bool DisableLineMarkers;
+  bool DumpDefines;
+  bool UseLineDirective;
+public:
+  PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
+                           bool lineMarkers, bool defines)
+     : PP(pp), ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
+       DumpDefines(defines) {
+    CurLine = 0;
+    CurFilename += "<uninit>";
+    EmittedTokensOnThisLine = false;
+    EmittedMacroOnThisLine = false;
+    FileType = SrcMgr::C_User;
+    Initialized = false;
+         
+    // If we're in microsoft mode, use normal #line instead of line markers.
+    UseLineDirective = PP.getLangOptions().Microsoft;
+  }
+
+  void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
+  bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
+
+  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+                           SrcMgr::CharacteristicKind FileType);
+  virtual void Ident(SourceLocation Loc, const std::string &str);
+  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+                             const std::string &Str);
+
+
+  bool HandleFirstTokOnLine(Token &Tok);
+  bool MoveToLine(SourceLocation Loc);
+  bool AvoidConcat(const Token &PrevTok, const Token &Tok) {
+    return ConcatInfo.AvoidConcat(PrevTok, Tok);
+  }
+  void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+
+  void HandleNewlinesInToken(const char *TokStr, unsigned Len);
+
+  /// MacroDefined - This hook is called whenever a macro definition is seen.
+  void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
+
+};
+}  // end anonymous namespace
+
+void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
+                                             const char *Extra,
+                                             unsigned ExtraLen) {
+  if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
+    OS << '\n';
+    EmittedTokensOnThisLine = false;
+    EmittedMacroOnThisLine = false;
+  }
+
+  // Emit #line directives or GNU line markers depending on what mode we're in.
+  if (UseLineDirective) {
+    OS << "#line" << ' ' << LineNo << ' ' << '"';
+    OS.write(&CurFilename[0], CurFilename.size());
+    OS << '"';
+  } else {
+    OS << '#' << ' ' << LineNo << ' ' << '"';
+    OS.write(&CurFilename[0], CurFilename.size());
+    OS << '"';
+    
+    if (ExtraLen)
+      OS.write(Extra, ExtraLen);
+
+    if (FileType == SrcMgr::C_System)
+      OS.write(" 3", 2);
+    else if (FileType == SrcMgr::C_ExternCSystem)
+      OS.write(" 3 4", 4);
+  }
+  OS << '\n';
+}
+
+/// MoveToLine - Move the output to the source line specified by the location
+/// object.  We can do this by emitting some number of \n's, or be emitting a
+/// #line directive.  This returns false if already at the specified line, true
+/// if some newlines were emitted.
+bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) {
+  unsigned LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc);
+
+  if (DisableLineMarkers) {
+    if (LineNo == CurLine) return false;
+
+    CurLine = LineNo;
+
+    if (!EmittedTokensOnThisLine && !EmittedMacroOnThisLine)
+      return true;
+
+    OS << '\n';
+    EmittedTokensOnThisLine = false;
+    EmittedMacroOnThisLine = false;
+    return true;
+  }
+
+  // If this line is "close enough" to the original line, just print newlines,
+  // otherwise print a #line directive.
+  if (LineNo-CurLine <= 8) {
+    if (LineNo-CurLine == 1)
+      OS << '\n';
+    else if (LineNo == CurLine)
+      return false;    // Spelling line moved, but instantiation line didn't.
+    else {
+      const char *NewLines = "\n\n\n\n\n\n\n\n";
+      OS.write(NewLines, LineNo-CurLine);
+    }
+  } else {
+    WriteLineInfo(LineNo, 0, 0);
+  }
+
+  CurLine = LineNo;
+  return true;
+}
+
+
+/// FileChanged - Whenever the preprocessor enters or exits a #include file
+/// it invokes this handler.  Update our conception of the current source
+/// position.
+void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
+                                           FileChangeReason Reason,
+                                       SrcMgr::CharacteristicKind NewFileType) {
+  // Unless we are exiting a #include, make sure to skip ahead to the line the
+  // #include directive was at.
+  SourceManager &SourceMgr = PP.getSourceManager();
+  if (Reason == PPCallbacks::EnterFile) {
+    SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc();
+    if (IncludeLoc.isValid())
+      MoveToLine(IncludeLoc);
+  } else if (Reason == PPCallbacks::SystemHeaderPragma) {
+    MoveToLine(Loc);
+
+    // TODO GCC emits the # directive for this directive on the line AFTER the
+    // directive and emits a bunch of spaces that aren't needed.  Emulate this
+    // strange behavior.
+  }
+
+  Loc = SourceMgr.getInstantiationLoc(Loc);
+  // FIXME: Should use presumed line #!
+  CurLine = SourceMgr.getInstantiationLineNumber(Loc);
+
+  if (DisableLineMarkers) return;
+
+  CurFilename.clear();
+  CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename();
+  Lexer::Stringify(CurFilename);
+  FileType = NewFileType;
+
+  if (!Initialized) {
+    WriteLineInfo(CurLine);
+    Initialized = true;
+  }
+
+  switch (Reason) {
+  case PPCallbacks::EnterFile:
+    WriteLineInfo(CurLine, " 1", 2);
+    break;
+  case PPCallbacks::ExitFile:
+    WriteLineInfo(CurLine, " 2", 2);
+    break;
+  case PPCallbacks::SystemHeaderPragma:
+  case PPCallbacks::RenameFile:
+    WriteLineInfo(CurLine);
+    break;
+  }
+}
+
+/// Ident - Handle #ident directives when read by the preprocessor.
+///
+void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
+  MoveToLine(Loc);
+
+  OS.write("#ident ", strlen("#ident "));
+  OS.write(&S[0], S.size());
+  EmittedTokensOnThisLine = true;
+}
+
+/// MacroDefined - This hook is called whenever a macro definition is seen.
+void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II,
+                                            const MacroInfo *MI) {
+  // Only print out macro definitions in -dD mode.
+  if (!DumpDefines ||
+      // Ignore __FILE__ etc.
+      MI->isBuiltinMacro()) return;
+
+  MoveToLine(MI->getDefinitionLoc());
+  PrintMacroDefinition(*II, *MI, PP, OS);
+  EmittedMacroOnThisLine = true;
+}
+
+
+void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
+                                             const IdentifierInfo *Kind,
+                                             const std::string &Str) {
+  MoveToLine(Loc);
+  OS << "#pragma comment(" << Kind->getName();
+
+  if (!Str.empty()) {
+    OS << ", \"";
+
+    for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+      unsigned char Char = Str[i];
+      if (isprint(Char) && Char != '\\' && Char != '"')
+        OS << (char)Char;
+      else  // Output anything hard as an octal escape.
+        OS << '\\'
+           << (char)('0'+ ((Char >> 6) & 7))
+           << (char)('0'+ ((Char >> 3) & 7))
+           << (char)('0'+ ((Char >> 0) & 7));
+    }
+    OS << '"';
+  }
+
+  OS << ')';
+  EmittedTokensOnThisLine = true;
+}
+
+
+/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
+/// is called for the first token on each new line.  If this really is the start
+/// of a new logical line, handle it and return true, otherwise return false.
+/// This may not be the start of a logical line because the "start of line"
+/// marker is set for spelling lines, not instantiation ones.
+bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
+  // Figure out what line we went to and insert the appropriate number of
+  // newline characters.
+  if (!MoveToLine(Tok.getLocation()))
+    return false;
+
+  // Print out space characters so that the first token on a line is
+  // indented for easy reading.
+  const SourceManager &SourceMgr = PP.getSourceManager();
+  unsigned ColNo = SourceMgr.getInstantiationColumnNumber(Tok.getLocation());
+
+  // This hack prevents stuff like:
+  // #define HASH #
+  // HASH define foo bar
+  // From having the # character end up at column 1, which makes it so it
+  // is not handled as a #define next time through the preprocessor if in
+  // -fpreprocessed mode.
+  if (ColNo <= 1 && Tok.is(tok::hash))
+    OS << ' ';
+
+  // Otherwise, indent the appropriate number of spaces.
+  for (; ColNo > 1; --ColNo)
+    OS << ' ';
+
+  return true;
+}
+
+void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
+                                                     unsigned Len) {
+  unsigned NumNewlines = 0;
+  for (; Len; --Len, ++TokStr) {
+    if (*TokStr != '\n' &&
+        *TokStr != '\r')
+      continue;
+
+    ++NumNewlines;
+
+    // If we have \n\r or \r\n, skip both and count as one line.
+    if (Len != 1 &&
+        (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+        TokStr[0] != TokStr[1])
+      ++TokStr, --Len;
+  }
+
+  if (NumNewlines == 0) return;
+
+  CurLine += NumNewlines;
+}
+
+
+namespace {
+struct UnknownPragmaHandler : public PragmaHandler {
+  const char *Prefix;
+  PrintPPOutputPPCallbacks *Callbacks;
+
+  UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks)
+    : PragmaHandler(0), Prefix(prefix), Callbacks(callbacks) {}
+  virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) {
+    // Figure out what line we went to and insert the appropriate number of
+    // newline characters.
+    Callbacks->MoveToLine(PragmaTok.getLocation());
+    Callbacks->OS.write(Prefix, strlen(Prefix));
+
+    // Read and print all of the pragma tokens.
+    while (PragmaTok.isNot(tok::eom)) {
+      if (PragmaTok.hasLeadingSpace())
+        Callbacks->OS << ' ';
+      std::string TokSpell = PP.getSpelling(PragmaTok);
+      Callbacks->OS.write(&TokSpell[0], TokSpell.size());
+      PP.LexUnexpandedToken(PragmaTok);
+    }
+    Callbacks->OS << '\n';
+  }
+};
+} // end anonymous namespace
+
+
+static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
+                                    PrintPPOutputPPCallbacks *Callbacks,
+                                    llvm::raw_ostream &OS) {
+  char Buffer[256];
+  Token PrevTok;
+  while (1) {
+
+    // If this token is at the start of a line, emit newlines if needed.
+    if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
+      // done.
+    } else if (Tok.hasLeadingSpace() ||
+               // If we haven't emitted a token on this line yet, PrevTok isn't
+               // useful to look at and no concatenation could happen anyway.
+               (Callbacks->hasEmittedTokensOnThisLine() &&
+                // Don't print "-" next to "-", it would form "--".
+                Callbacks->AvoidConcat(PrevTok, Tok))) {
+      OS << ' ';
+    }
+
+    if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
+      OS << II->getName();
+    } else if (Tok.isLiteral() && !Tok.needsCleaning() &&
+               Tok.getLiteralData()) {
+      OS.write(Tok.getLiteralData(), Tok.getLength());
+    } else if (Tok.getLength() < 256) {
+      const char *TokPtr = Buffer;
+      unsigned Len = PP.getSpelling(Tok, TokPtr);
+      OS.write(TokPtr, Len);
+
+      // Tokens that can contain embedded newlines need to adjust our current
+      // line number.
+      if (Tok.getKind() == tok::comment)
+        Callbacks->HandleNewlinesInToken(TokPtr, Len);
+    } else {
+      std::string S = PP.getSpelling(Tok);
+      OS.write(&S[0], S.size());
+
+      // Tokens that can contain embedded newlines need to adjust our current
+      // line number.
+      if (Tok.getKind() == tok::comment)
+        Callbacks->HandleNewlinesInToken(&S[0], S.size());
+    }
+    Callbacks->SetEmittedTokensOnThisLine();
+
+    if (Tok.is(tok::eof)) break;
+
+    PrevTok = Tok;
+    PP.Lex(Tok);
+  }
+}
+
+typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
+static int MacroIDCompare(const void* a, const void* b) {
+  const id_macro_pair *LHS = static_cast<const id_macro_pair*>(a);
+  const id_macro_pair *RHS = static_cast<const id_macro_pair*>(b);
+  return LHS->first->getName().compare(RHS->first->getName());
+}
+
+static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
+  // -dM mode just scans and ignores all tokens in the files, then dumps out
+  // the macro table at the end.
+  PP.EnterMainSourceFile();
+
+  Token Tok;
+  do PP.Lex(Tok);
+  while (Tok.isNot(tok::eof));
+
+  llvm::SmallVector<id_macro_pair, 128>
+    MacrosByID(PP.macro_begin(), PP.macro_end());
+  llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
+
+  for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
+    MacroInfo &MI = *MacrosByID[i].second;
+    // Ignore computed macros like __LINE__ and friends.
+    if (MI.isBuiltinMacro()) continue;
+
+    PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS);
+    *OS << '\n';
+  }
+}
+
+/// DoPrintPreprocessedInput - This implements -E mode.
+///
+void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
+                                     const PreprocessorOutputOptions &Opts) {
+  // Show macros with no output is handled specially.
+  if (!Opts.ShowCPP) {
+    assert(Opts.ShowMacros && "Not yet implemented!");
+    DoPrintMacros(PP, OS);
+    return;
+  }
+
+  // Inform the preprocessor whether we want it to retain comments or not, due
+  // to -C or -CC.
+  PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
+
+  OS->SetBufferSize(64*1024);
+
+  PrintPPOutputPPCallbacks *Callbacks =
+      new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
+                                   Opts.ShowMacros);
+  PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
+  PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
+                                                      Callbacks));
+
+  PP.setPPCallbacks(Callbacks);
+
+  // After we have configured the preprocessor, enter the main file.
+  PP.EnterMainSourceFile();
+
+  // Consume all of the tokens that come from the predefines buffer.  Those
+  // should not be emitted into the output and are guaranteed to be at the
+  // start.
+  const SourceManager &SourceMgr = PP.getSourceManager();
+  Token Tok;
+  do PP.Lex(Tok);
+  while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() &&
+         !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(),
+                 "<built-in>"));
+
+  // Read all the preprocessed tokens, printing them out to the stream.
+  PrintPreprocessedTokens(PP, Tok, Callbacks, *OS);
+  *OS << '\n';
+}
+
diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp
new file mode 100644
index 0000000..0bcbd4f
--- /dev/null
+++ b/lib/Frontend/RewriteMacros.cpp
@@ -0,0 +1,217 @@
+//===--- RewriteMacros.cpp - Rewrite macros into their expansions ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code rewrites macro invocations into their expansions.  This gives you
+// a macro expanded file that retains comments and #includes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <cstdio>
+
+using namespace clang;
+
+/// isSameToken - Return true if the two specified tokens start have the same
+/// content.
+static bool isSameToken(Token &RawTok, Token &PPTok) {
+  // If two tokens have the same kind and the same identifier info, they are
+  // obviously the same.
+  if (PPTok.getKind() == RawTok.getKind() &&
+      PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
+    return true;
+
+  // Otherwise, if they are different but have the same identifier info, they
+  // are also considered to be the same.  This allows keywords and raw lexed
+  // identifiers with the same name to be treated the same.
+  if (PPTok.getIdentifierInfo() &&
+      PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
+    return true;
+
+  return false;
+}
+
+
+/// GetNextRawTok - Return the next raw token in the stream, skipping over
+/// comments if ReturnComment is false.
+static const Token &GetNextRawTok(const std::vector<Token> &RawTokens,
+                                  unsigned &CurTok, bool ReturnComment) {
+  assert(CurTok < RawTokens.size() && "Overran eof!");
+
+  // If the client doesn't want comments and we have one, skip it.
+  if (!ReturnComment && RawTokens[CurTok].is(tok::comment))
+    ++CurTok;
+
+  return RawTokens[CurTok++];
+}
+
+
+/// LexRawTokensFromMainFile - Lets all the raw tokens from the main file into
+/// the specified vector.
+static void LexRawTokensFromMainFile(Preprocessor &PP,
+                                     std::vector<Token> &RawTokens) {
+  SourceManager &SM = PP.getSourceManager();
+
+  // Create a lexer to lex all the tokens of the main file in raw mode.  Even
+  // though it is in raw mode, it will not return comments.
+  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
+  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
+
+  // Switch on comment lexing because we really do want them.
+  RawLex.SetCommentRetentionState(true);
+
+  Token RawTok;
+  do {
+    RawLex.LexFromRawLexer(RawTok);
+
+    // If we have an identifier with no identifier info for our raw token, look
+    // up the indentifier info.  This is important for equality comparison of
+    // identifier tokens.
+    if (RawTok.is(tok::identifier) && !RawTok.getIdentifierInfo())
+      RawTok.setIdentifierInfo(PP.LookUpIdentifierInfo(RawTok));
+
+    RawTokens.push_back(RawTok);
+  } while (RawTok.isNot(tok::eof));
+}
+
+
+/// RewriteMacrosInInput - Implement -rewrite-macros mode.
+void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) {
+  SourceManager &SM = PP.getSourceManager();
+
+  Rewriter Rewrite;
+  Rewrite.setSourceMgr(SM, PP.getLangOptions());
+  RewriteBuffer &RB = Rewrite.getEditBuffer(SM.getMainFileID());
+
+  std::vector<Token> RawTokens;
+  LexRawTokensFromMainFile(PP, RawTokens);
+  unsigned CurRawTok = 0;
+  Token RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+
+
+  // Get the first preprocessing token.
+  PP.EnterMainSourceFile();
+  Token PPTok;
+  PP.Lex(PPTok);
+
+  // Preprocess the input file in parallel with raw lexing the main file. Ignore
+  // all tokens that are preprocessed from a file other than the main file (e.g.
+  // a header).  If we see tokens that are in the preprocessed file but not the
+  // lexed file, we have a macro expansion.  If we see tokens in the lexed file
+  // that aren't in the preprocessed view, we have macros that expand to no
+  // tokens, or macro arguments etc.
+  while (RawTok.isNot(tok::eof) || PPTok.isNot(tok::eof)) {
+    SourceLocation PPLoc = SM.getInstantiationLoc(PPTok.getLocation());
+
+    // If PPTok is from a different source file, ignore it.
+    if (!SM.isFromMainFile(PPLoc)) {
+      PP.Lex(PPTok);
+      continue;
+    }
+
+    // If the raw file hits a preprocessor directive, they will be extra tokens
+    // in the raw file that don't exist in the preprocsesed file.  However, we
+    // choose to preserve them in the output file and otherwise handle them
+    // specially.
+    if (RawTok.is(tok::hash) && RawTok.isAtStartOfLine()) {
+      // If this is a #warning directive or #pragma mark (GNU extensions),
+      // comment the line out.
+      if (RawTokens[CurRawTok].is(tok::identifier)) {
+        const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo();
+        if (II->getName() == "warning") {
+          // Comment out #warning.
+          RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
+        } else if (II->getName() == "pragma" &&
+                   RawTokens[CurRawTok+1].is(tok::identifier) &&
+                   (RawTokens[CurRawTok+1].getIdentifierInfo()->getName() ==
+                    "mark")) {
+          // Comment out #pragma mark.
+          RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
+        }
+      }
+
+      // Otherwise, if this is a #include or some other directive, just leave it
+      // in the file by skipping over the line.
+      RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+      while (!RawTok.isAtStartOfLine() && RawTok.isNot(tok::eof))
+        RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+      continue;
+    }
+
+    // Okay, both tokens are from the same file.  Get their offsets from the
+    // start of the file.
+    unsigned PPOffs = SM.getFileOffset(PPLoc);
+    unsigned RawOffs = SM.getFileOffset(RawTok.getLocation());
+
+    // If the offsets are the same and the token kind is the same, ignore them.
+    if (PPOffs == RawOffs && isSameToken(RawTok, PPTok)) {
+      RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+      PP.Lex(PPTok);
+      continue;
+    }
+
+    // If the PP token is farther along than the raw token, something was
+    // deleted.  Comment out the raw token.
+    if (RawOffs <= PPOffs) {
+      // Comment out a whole run of tokens instead of bracketing each one with
+      // comments.  Add a leading space if RawTok didn't have one.
+      bool HasSpace = RawTok.hasLeadingSpace();
+      RB.InsertTextAfter(RawOffs, " /*"+HasSpace);
+      unsigned EndPos;
+
+      do {
+        EndPos = RawOffs+RawTok.getLength();
+
+        RawTok = GetNextRawTok(RawTokens, CurRawTok, true);
+        RawOffs = SM.getFileOffset(RawTok.getLocation());
+
+        if (RawTok.is(tok::comment)) {
+          // Skip past the comment.
+          RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+          break;
+        }
+
+      } while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() &&
+               (PPOffs != RawOffs || !isSameToken(RawTok, PPTok)));
+
+      RB.InsertTextBefore(EndPos, "*/");
+      continue;
+    }
+
+    // Otherwise, there was a replacement an expansion.  Insert the new token
+    // in the output buffer.  Insert the whole run of new tokens at once to get
+    // them in the right order.
+    unsigned InsertPos = PPOffs;
+    std::string Expansion;
+    while (PPOffs < RawOffs) {
+      Expansion += ' ' + PP.getSpelling(PPTok);
+      PP.Lex(PPTok);
+      PPLoc = SM.getInstantiationLoc(PPTok.getLocation());
+      PPOffs = SM.getFileOffset(PPLoc);
+    }
+    Expansion += ' ';
+    RB.InsertTextBefore(InsertPos, Expansion);
+  }
+
+  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
+  // we are done.
+  if (const RewriteBuffer *RewriteBuf =
+      Rewrite.getRewriteBufferFor(SM.getMainFileID())) {
+    //printf("Changed:\n");
+    *OS << std::string(RewriteBuf->begin(), RewriteBuf->end());
+  } else {
+    fprintf(stderr, "No changes\n");
+  }
+  OS->flush();
+}
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
new file mode 100644
index 0000000..f5ff5bc
--- /dev/null
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -0,0 +1,5294 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/DenseSet.h"
+using namespace clang;
+using llvm::utostr;
+
+namespace {
+  class RewriteObjC : public ASTConsumer {
+    enum {
+      BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)), 
+                                        block, ... */
+      BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
+      BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the 
+                                        __block variable */
+      BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy 
+                                        helpers */
+      BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose 
+                                        support routines */
+      BLOCK_BYREF_CURRENT_MAX = 256
+    };
+    
+    enum {
+      BLOCK_NEEDS_FREE =        (1 << 24),
+      BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
+      BLOCK_HAS_CXX_OBJ =       (1 << 26),
+      BLOCK_IS_GC =             (1 << 27),
+      BLOCK_IS_GLOBAL =         (1 << 28),
+      BLOCK_HAS_DESCRIPTOR =    (1 << 29)
+    };
+    
+    Rewriter Rewrite;
+    Diagnostic &Diags;
+    const LangOptions &LangOpts;
+    unsigned RewriteFailedDiag;
+    unsigned TryFinallyContainsReturnDiag;
+
+    ASTContext *Context;
+    SourceManager *SM;
+    TranslationUnitDecl *TUDecl;
+    FileID MainFileID;
+    const char *MainFileStart, *MainFileEnd;
+    SourceLocation LastIncLoc;
+
+    llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
+    llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
+    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
+    llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
+    llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
+    llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
+    llvm::SmallVector<Stmt *, 32> Stmts;
+    llvm::SmallVector<int, 8> ObjCBcLabelNo;
+    // Remember all the @protocol(<expr>) expressions.
+    llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
+    
+    llvm::DenseSet<uint64_t> CopyDestroyCache;
+    
+    unsigned NumObjCStringLiterals;
+
+    FunctionDecl *MsgSendFunctionDecl;
+    FunctionDecl *MsgSendSuperFunctionDecl;
+    FunctionDecl *MsgSendStretFunctionDecl;
+    FunctionDecl *MsgSendSuperStretFunctionDecl;
+    FunctionDecl *MsgSendFpretFunctionDecl;
+    FunctionDecl *GetClassFunctionDecl;
+    FunctionDecl *GetMetaClassFunctionDecl;
+    FunctionDecl *SelGetUidFunctionDecl;
+    FunctionDecl *CFStringFunctionDecl;
+    FunctionDecl *SuperContructorFunctionDecl;
+
+    // ObjC string constant support.
+    VarDecl *ConstantStringClassReference;
+    RecordDecl *NSStringRecord;
+
+    // ObjC foreach break/continue generation support.
+    int BcLabelCount;
+
+    // Needed for super.
+    ObjCMethodDecl *CurMethodDef;
+    RecordDecl *SuperStructDecl;
+    RecordDecl *ConstantStringDecl;
+
+    TypeDecl *ProtocolTypeDecl;
+    QualType getProtocolType();
+
+    // Needed for header files being rewritten
+    bool IsHeader;
+
+    std::string InFileName;
+    llvm::raw_ostream* OutFile;
+
+    bool SilenceRewriteMacroWarning;
+    bool objc_impl_method;
+
+    std::string Preamble;
+
+    // Block expressions.
+    llvm::SmallVector<BlockExpr *, 32> Blocks;
+    llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
+    llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
+
+    // Block related declarations.
+    llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
+    llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
+    llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
+    llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
+
+    llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
+
+    // This maps a property to it's assignment statement.
+    llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters;
+    // This maps a property to it's synthesied message expression.
+    // This allows us to rewrite chained getters (e.g. o.a.b.c).
+    llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters;
+
+    // This maps an original source AST to it's rewritten form. This allows
+    // us to avoid rewriting the same node twice (which is very uncommon).
+    // This is needed to support some of the exotic property rewriting.
+    llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
+
+    FunctionDecl *CurFunctionDef;
+    FunctionDecl *CurFunctionDeclToDeclareForBlock;
+    VarDecl *GlobalVarDecl;
+
+    bool DisableReplaceStmt;
+
+    static const int OBJC_ABI_VERSION =7 ;
+  public:
+    virtual void Initialize(ASTContext &context);
+
+    // Top Level Driver code.
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        HandleTopLevelSingleDecl(*I);
+    }
+    void HandleTopLevelSingleDecl(Decl *D);
+    void HandleDeclInMainFile(Decl *D);
+    RewriteObjC(std::string inFile, llvm::raw_ostream *OS,
+                Diagnostic &D, const LangOptions &LOpts,
+                bool silenceMacroWarn);
+
+    ~RewriteObjC() {}
+
+    virtual void HandleTranslationUnit(ASTContext &C);
+
+    void ReplaceStmt(Stmt *Old, Stmt *New) {
+      Stmt *ReplacingStmt = ReplacedNodes[Old];
+
+      if (ReplacingStmt)
+        return; // We can't rewrite the same node twice.
+
+      if (DisableReplaceStmt)
+        return; // Used when rewriting the assignment of a property setter.
+
+      // If replacement succeeded or warning disabled return with no warning.
+      if (!Rewrite.ReplaceStmt(Old, New)) {
+        ReplacedNodes[Old] = New;
+        return;
+      }
+      if (SilenceRewriteMacroWarning)
+        return;
+      Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+                   << Old->getSourceRange();
+    }
+
+    void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
+      // Measaure the old text.
+      int Size = Rewrite.getRangeSize(SrcRange);
+      if (Size == -1) {
+        Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+                     << Old->getSourceRange();
+        return;
+      }
+      // Get the new text.
+      std::string SStr;
+      llvm::raw_string_ostream S(SStr);
+      New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
+      const std::string &Str = S.str();
+
+      // If replacement succeeded or warning disabled return with no warning.
+      if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
+        ReplacedNodes[Old] = New;
+        return;
+      }
+      if (SilenceRewriteMacroWarning)
+        return;
+      Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+                   << Old->getSourceRange();
+    }
+
+    void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
+                    bool InsertAfter = true) {
+      // If insertion succeeded or warning disabled return with no warning.
+      if (!Rewrite.InsertText(Loc, llvm::StringRef(StrData, StrLen),
+                              InsertAfter) ||
+          SilenceRewriteMacroWarning)
+        return;
+
+      Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
+    }
+
+    void RemoveText(SourceLocation Loc, unsigned StrLen) {
+      // If removal succeeded or warning disabled return with no warning.
+      if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning)
+        return;
+
+      Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
+    }
+
+    void ReplaceText(SourceLocation Start, unsigned OrigLength,
+                     const char *NewStr, unsigned NewLength) {
+      // If removal succeeded or warning disabled return with no warning.
+      if (!Rewrite.ReplaceText(Start, OrigLength,
+                               llvm::StringRef(NewStr, NewLength)) ||
+          SilenceRewriteMacroWarning)
+        return;
+
+      Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
+    }
+
+    // Syntactic Rewriting.
+    void RewritePrologue(SourceLocation Loc);
+    void RewriteInclude();
+    void RewriteTabs();
+    void RewriteForwardClassDecl(ObjCClassDecl *Dcl);
+    void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
+                                 ObjCImplementationDecl *IMD,
+                                 ObjCCategoryImplDecl *CID);
+    void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
+    void RewriteImplementationDecl(Decl *Dcl);
+    void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr);
+    void RewriteByRefString(std::string &ResultStr, const std::string &Name,
+                            ValueDecl *VD);
+    void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
+    void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
+    void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl);
+    void RewriteMethodDeclaration(ObjCMethodDecl *Method);
+    void RewriteProperty(ObjCPropertyDecl *prop);
+    void RewriteFunctionDecl(FunctionDecl *FD);
+    void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
+    void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
+    void RewriteObjCQualifiedInterfaceTypes(Expr *E);
+    bool needToScanForQualifiers(QualType T);
+    ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr);
+    QualType getSuperStructType();
+    QualType getConstantStringStructType();
+    bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
+
+    // Expression Rewriting.
+    Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
+    void CollectPropertySetters(Stmt *S);
+
+    Stmt *CurrentBody;
+    ParentMap *PropParentMap; // created lazily.
+
+    Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
+    Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,
+                                 bool &replaced);
+    Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
+    Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
+    Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+                                SourceRange SrcRange);
+    Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
+    Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
+    Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
+    Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
+    void WarnAboutReturnGotoStmts(Stmt *S);
+    void HasReturnStmts(Stmt *S, bool &hasReturns);
+    void RewriteTryReturnStmts(Stmt *S);
+    void RewriteSyncReturnStmts(Stmt *S, std::string buf);
+    Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
+    Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+    Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
+    Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S);
+    Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
+    Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
+                                       SourceLocation OrigEnd);
+    CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
+                                           Expr **args, unsigned nargs);
+    Stmt *SynthMessageExpr(ObjCMessageExpr *Exp);
+    Stmt *RewriteBreakStmt(BreakStmt *S);
+    Stmt *RewriteContinueStmt(ContinueStmt *S);
+    void SynthCountByEnumWithState(std::string &buf);
+
+    void SynthMsgSendFunctionDecl();
+    void SynthMsgSendSuperFunctionDecl();
+    void SynthMsgSendStretFunctionDecl();
+    void SynthMsgSendFpretFunctionDecl();
+    void SynthMsgSendSuperStretFunctionDecl();
+    void SynthGetClassFunctionDecl();
+    void SynthGetMetaClassFunctionDecl();
+    void SynthSelGetUidFunctionDecl();
+    void SynthSuperContructorFunctionDecl();
+
+    // Metadata emission.
+    void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+                                  std::string &Result);
+
+    void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
+                                     std::string &Result);
+
+    template<typename MethodIterator>
+    void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+                                    MethodIterator MethodEnd,
+                                    bool IsInstanceMethod,
+                                    const char *prefix,
+                                    const char *ClassName,
+                                    std::string &Result);
+
+    void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
+                                     const char *prefix,
+                                     const char *ClassName,
+                                     std::string &Result);
+    void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
+                                         const char *prefix,
+                                         const char *ClassName,
+                                         std::string &Result);
+    void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
+                                      std::string &Result);
+    void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl,
+                                         ObjCIvarDecl *ivar,
+                                         std::string &Result);
+    void RewriteImplementations();
+    void SynthesizeMetaDataIntoBuffer(std::string &Result);
+
+    // Block rewriting.
+    void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
+    void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
+
+    void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
+    void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
+
+    // Block specific rewrite rules.
+    void RewriteBlockCall(CallExpr *Exp);
+    void RewriteBlockPointerDecl(NamedDecl *VD);
+    void RewriteByRefVar(VarDecl *VD);
+    std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
+    Stmt *RewriteBlockDeclRefExpr(Expr *VD);
+    void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
+
+    std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
+                                      const char *funcName, std::string Tag);
+    std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
+                                      const char *funcName, std::string Tag);
+    std::string SynthesizeBlockImpl(BlockExpr *CE, 
+                                    std::string Tag, std::string Desc);
+    std::string SynthesizeBlockDescriptor(std::string DescTag, 
+                                          std::string ImplTag,
+                                          int i, const char *funcName,
+                                          unsigned hasCopy);
+    Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
+    void SynthesizeBlockLiterals(SourceLocation FunLocStart,
+                                 const char *FunName);
+    void RewriteRecordBody(RecordDecl *RD);
+
+    void CollectBlockDeclRefInfo(BlockExpr *Exp);
+    void GetBlockCallExprs(Stmt *S);
+    void GetBlockDeclRefExprs(Stmt *S);
+
+    // We avoid calling Type::isBlockPointerType(), since it operates on the
+    // canonical type. We only care if the top-level type is a closure pointer.
+    bool isTopLevelBlockPointerType(QualType T) {
+      return isa<BlockPointerType>(T);
+    }
+
+    // FIXME: This predicate seems like it would be useful to add to ASTContext.
+    bool isObjCType(QualType T) {
+      if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
+        return false;
+
+      QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
+
+      if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
+          OCT == Context->getCanonicalType(Context->getObjCClassType()))
+        return true;
+
+      if (const PointerType *PT = OCT->getAs<PointerType>()) {
+        if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
+            PT->getPointeeType()->isObjCQualifiedIdType())
+          return true;
+      }
+      return false;
+    }
+    bool PointerTypeTakesAnyBlockArguments(QualType QT);
+    void GetExtentOfArgList(const char *Name, const char *&LParen,
+                            const char *&RParen);
+    void RewriteCastExpr(CStyleCastExpr *CE);
+
+    FunctionDecl *SynthBlockInitFunctionDecl(const char *name);
+    Stmt *SynthBlockInitExpr(BlockExpr *Exp);
+
+    void QuoteDoublequotes(std::string &From, std::string &To) {
+      for (unsigned i = 0; i < From.length(); i++) {
+        if (From[i] == '"')
+          To += "\\\"";
+        else
+          To += From[i];
+      }
+    }
+  };
+
+  // Helper function: create a CStyleCastExpr with trivial type source info.
+  CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
+                                           CastExpr::CastKind Kind, Expr *E) {
+    TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
+    return new (Ctx) CStyleCastExpr(Ty, Kind, E, TInfo,
+                                    SourceLocation(), SourceLocation());
+  }
+}
+
+void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
+                                                   NamedDecl *D) {
+  if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) {
+    for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
+         E = fproto->arg_type_end(); I && (I != E); ++I)
+      if (isTopLevelBlockPointerType(*I)) {
+        // All the args are checked/rewritten. Don't call twice!
+        RewriteBlockPointerDecl(D);
+        break;
+      }
+  }
+}
+
+void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
+  const PointerType *PT = funcType->getAs<PointerType>();
+  if (PT && PointerTypeTakesAnyBlockArguments(funcType))
+    RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
+}
+
+static bool IsHeaderFile(const std::string &Filename) {
+  std::string::size_type DotPos = Filename.rfind('.');
+
+  if (DotPos == std::string::npos) {
+    // no file extension
+    return false;
+  }
+
+  std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
+  // C header: .h
+  // C++ header: .hh or .H;
+  return Ext == "h" || Ext == "hh" || Ext == "H";
+}
+
+RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS,
+                         Diagnostic &D, const LangOptions &LOpts,
+                         bool silenceMacroWarn)
+      : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
+        SilenceRewriteMacroWarning(silenceMacroWarn) {
+  IsHeader = IsHeaderFile(inFile);
+  RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
+               "rewriting sub-expression within a macro (may not be correct)");
+  TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning,
+               "rewriter doesn't support user-specified control flow semantics "
+               "for @try/@finally (code may not execute properly)");
+}
+
+ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
+                                       llvm::raw_ostream* OS,
+                                       Diagnostic &Diags,
+                                       const LangOptions &LOpts,
+                                       bool SilenceRewriteMacroWarning) {
+  return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+}
+
+void RewriteObjC::Initialize(ASTContext &context) {
+  Context = &context;
+  SM = &Context->getSourceManager();
+  TUDecl = Context->getTranslationUnitDecl();
+  MsgSendFunctionDecl = 0;
+  MsgSendSuperFunctionDecl = 0;
+  MsgSendStretFunctionDecl = 0;
+  MsgSendSuperStretFunctionDecl = 0;
+  MsgSendFpretFunctionDecl = 0;
+  GetClassFunctionDecl = 0;
+  GetMetaClassFunctionDecl = 0;
+  SelGetUidFunctionDecl = 0;
+  CFStringFunctionDecl = 0;
+  ConstantStringClassReference = 0;
+  NSStringRecord = 0;
+  CurMethodDef = 0;
+  CurFunctionDef = 0;
+  CurFunctionDeclToDeclareForBlock = 0;
+  GlobalVarDecl = 0;
+  SuperStructDecl = 0;
+  ProtocolTypeDecl = 0;
+  ConstantStringDecl = 0;
+  BcLabelCount = 0;
+  SuperContructorFunctionDecl = 0;
+  NumObjCStringLiterals = 0;
+  PropParentMap = 0;
+  CurrentBody = 0;
+  DisableReplaceStmt = false;
+  objc_impl_method = false;
+
+  // Get the ID and start/end of the main file.
+  MainFileID = SM->getMainFileID();
+  const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
+  MainFileStart = MainBuf->getBufferStart();
+  MainFileEnd = MainBuf->getBufferEnd();
+
+  Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
+
+  // declaring objc_selector outside the parameter list removes a silly
+  // scope related warning...
+  if (IsHeader)
+    Preamble = "#pragma once\n";
+  Preamble += "struct objc_selector; struct objc_class;\n";
+  Preamble += "struct __rw_objc_super { struct objc_object *object; ";
+  Preamble += "struct objc_object *superClass; ";
+  if (LangOpts.Microsoft) {
+    // Add a constructor for creating temporary objects.
+    Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
+                ": ";
+    Preamble += "object(o), superClass(s) {} ";
+  }
+  Preamble += "};\n";
+  Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
+  Preamble += "typedef struct objc_object Protocol;\n";
+  Preamble += "#define _REWRITER_typedef_Protocol\n";
+  Preamble += "#endif\n";
+  if (LangOpts.Microsoft) {
+    Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
+    Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
+  } else
+    Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
+  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
+  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret";
+  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret";
+  Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
+  Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
+  Preamble += "(const char *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
+  Preamble += "(const char *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
+  Preamble += "(struct objc_class *, struct objc_object *);\n";
+  // @synchronized hooks.
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
+  Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
+  Preamble += "struct __objcFastEnumerationState {\n\t";
+  Preamble += "unsigned long state;\n\t";
+  Preamble += "void **itemsPtr;\n\t";
+  Preamble += "unsigned long *mutationsPtr;\n\t";
+  Preamble += "unsigned long extra[5];\n};\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
+  Preamble += "#define __FASTENUMERATIONSTATE\n";
+  Preamble += "#endif\n";
+  Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
+  Preamble += "struct __NSConstantStringImpl {\n";
+  Preamble += "  int *isa;\n";
+  Preamble += "  int flags;\n";
+  Preamble += "  char *str;\n";
+  Preamble += "  long length;\n";
+  Preamble += "};\n";
+  Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
+  Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
+  Preamble += "#else\n";
+  Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
+  Preamble += "#endif\n";
+  Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
+  Preamble += "#endif\n";
+  // Blocks preamble.
+  Preamble += "#ifndef BLOCK_IMPL\n";
+  Preamble += "#define BLOCK_IMPL\n";
+  Preamble += "struct __block_impl {\n";
+  Preamble += "  void *isa;\n";
+  Preamble += "  int Flags;\n";
+  Preamble += "  int Reserved;\n";
+  Preamble += "  void *FuncPtr;\n";
+  Preamble += "};\n";
+  Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
+  Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int);\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
+  Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
+  Preamble += "#else\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
+  Preamble += "#endif\n";
+  Preamble += "#endif\n";
+  if (LangOpts.Microsoft) {
+    Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
+    Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
+    Preamble += "#define __attribute__(X)\n";
+    Preamble += "#define __weak\n";
+  }
+  else {
+    Preamble += "#define __block\n";
+    Preamble += "#define __weak\n";
+  }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Top Level Driver Code
+//===----------------------------------------------------------------------===//
+
+void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
+  if (Diags.hasErrorOccurred())
+    return;
+
+  // Two cases: either the decl could be in the main file, or it could be in a
+  // #included file.  If the former, rewrite it now.  If the later, check to see
+  // if we rewrote the #include/#import.
+  SourceLocation Loc = D->getLocation();
+  Loc = SM->getInstantiationLoc(Loc);
+
+  // If this is for a builtin, ignore it.
+  if (Loc.isInvalid()) return;
+
+  // Look for built-in declarations that we need to refer during the rewrite.
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    RewriteFunctionDecl(FD);
+  } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
+    // declared in <Foundation/NSString.h>
+    if (strcmp(FVD->getNameAsCString(), "_NSConstantStringClassReference") == 0) {
+      ConstantStringClassReference = FVD;
+      return;
+    }
+  } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
+    RewriteInterfaceDecl(MD);
+  } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
+    RewriteCategoryDecl(CD);
+  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+    RewriteProtocolDecl(PD);
+  } else if (ObjCForwardProtocolDecl *FP =
+             dyn_cast<ObjCForwardProtocolDecl>(D)){
+    RewriteForwardProtocolDecl(FP);
+  } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
+    // Recurse into linkage specifications
+    for (DeclContext::decl_iterator DI = LSD->decls_begin(),
+                                 DIEnd = LSD->decls_end();
+         DI != DIEnd; ++DI)
+      HandleTopLevelSingleDecl(*DI);
+  }
+  // If we have a decl in the main file, see if we should rewrite it.
+  if (SM->isFromMainFile(Loc))
+    return HandleDeclInMainFile(D);
+}
+
+//===----------------------------------------------------------------------===//
+// Syntactic (non-AST) Rewriting Code
+//===----------------------------------------------------------------------===//
+
+void RewriteObjC::RewriteInclude() {
+  SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
+  std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
+  const char *MainBufStart = MainBuf.first;
+  const char *MainBufEnd = MainBuf.second;
+  size_t ImportLen = strlen("import");
+  size_t IncludeLen = strlen("include");
+
+  // Loop over the whole file, looking for includes.
+  for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
+    if (*BufPtr == '#') {
+      if (++BufPtr == MainBufEnd)
+        return;
+      while (*BufPtr == ' ' || *BufPtr == '\t')
+        if (++BufPtr == MainBufEnd)
+          return;
+      if (!strncmp(BufPtr, "import", ImportLen)) {
+        // replace import with include
+        SourceLocation ImportLoc =
+          LocStart.getFileLocWithOffset(BufPtr-MainBufStart);
+        ReplaceText(ImportLoc, ImportLen, "include", IncludeLen);
+        BufPtr += ImportLen;
+      }
+    }
+  }
+}
+
+void RewriteObjC::RewriteTabs() {
+  std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
+  const char *MainBufStart = MainBuf.first;
+  const char *MainBufEnd = MainBuf.second;
+
+  // Loop over the whole file, looking for tabs.
+  for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
+    if (*BufPtr != '\t')
+      continue;
+
+    // Okay, we found a tab.  This tab will turn into at least one character,
+    // but it depends on which 'virtual column' it is in.  Compute that now.
+    unsigned VCol = 0;
+    while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
+           BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
+      ++VCol;
+
+    // Okay, now that we know the virtual column, we know how many spaces to
+    // insert.  We assume 8-character tab-stops.
+    unsigned Spaces = 8-(VCol & 7);
+
+    // Get the location of the tab.
+    SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID);
+    TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart);
+
+    // Rewrite the single tab character into a sequence of spaces.
+    ReplaceText(TabLoc, 1, "        ", Spaces);
+  }
+}
+
+static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
+                                       ObjCIvarDecl *OID) {
+  std::string S;
+  S = "((struct ";
+  S += ClassDecl->getIdentifier()->getName();
+  S += "_IMPL *)self)->";
+  S += OID->getName();
+  return S;
+}
+
+void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
+                                          ObjCImplementationDecl *IMD,
+                                          ObjCCategoryImplDecl *CID) {
+  SourceLocation startLoc = PID->getLocStart();
+  InsertText(startLoc, "// ", 3);
+  const char *startBuf = SM->getCharacterData(startLoc);
+  assert((*startBuf == '@') && "bogus @synthesize location");
+  const char *semiBuf = strchr(startBuf, ';');
+  assert((*semiBuf == ';') && "@synthesize: can't find ';'");
+  SourceLocation onePastSemiLoc =
+    startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+  if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+    return; // FIXME: is this correct?
+
+  // Generate the 'getter' function.
+  ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  ObjCInterfaceDecl *ClassDecl = PD->getGetterMethodDecl()->getClassInterface();
+  ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
+
+  if (!OID)
+    return;
+
+  std::string Getr;
+  RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr);
+  Getr += "{ ";
+  // Synthesize an explicit cast to gain access to the ivar.
+  // FIXME: deal with code generation implications for various property
+  // attributes (copy, retain, nonatomic).
+  // See objc-act.c:objc_synthesize_new_getter() for details.
+  Getr += "return " + getIvarAccessString(ClassDecl, OID);
+  Getr += "; }";
+  InsertText(onePastSemiLoc, Getr.c_str(), Getr.size());
+  if (PD->isReadOnly())
+    return;
+
+  // Generate the 'setter' function.
+  std::string Setr;
+  RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr);
+  Setr += "{ ";
+  // Synthesize an explicit cast to initialize the ivar.
+  // FIXME: deal with code generation implications for various property
+  // attributes (copy, retain, nonatomic).
+  // See objc-act.c:objc_synthesize_new_setter() for details.
+  Setr += getIvarAccessString(ClassDecl, OID) + " = ";
+  Setr += PD->getNameAsCString();
+  Setr += "; }";
+  InsertText(onePastSemiLoc, Setr.c_str(), Setr.size());
+}
+
+void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
+  // Get the start location and compute the semi location.
+  SourceLocation startLoc = ClassDecl->getLocation();
+  const char *startBuf = SM->getCharacterData(startLoc);
+  const char *semiPtr = strchr(startBuf, ';');
+
+  // Translate to typedef's that forward reference structs with the same name
+  // as the class. As a convenience, we include the original declaration
+  // as a comment.
+  std::string typedefString;
+  typedefString += "// @class ";
+  for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
+       I != E; ++I) {
+    ObjCInterfaceDecl *ForwardDecl = I->getInterface();
+    typedefString += ForwardDecl->getNameAsString();
+    if (I+1 != E)
+      typedefString += ", ";
+    else
+      typedefString += ";\n";
+  }
+  
+  for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
+       I != E; ++I) {
+    ObjCInterfaceDecl *ForwardDecl = I->getInterface();
+    typedefString += "#ifndef _REWRITER_typedef_";
+    typedefString += ForwardDecl->getNameAsString();
+    typedefString += "\n";
+    typedefString += "#define _REWRITER_typedef_";
+    typedefString += ForwardDecl->getNameAsString();
+    typedefString += "\n";
+    typedefString += "typedef struct objc_object ";
+    typedefString += ForwardDecl->getNameAsString();
+    typedefString += ";\n#endif\n";
+  }
+
+  // Replace the @class with typedefs corresponding to the classes.
+  ReplaceText(startLoc, semiPtr-startBuf+1,
+              typedefString.c_str(), typedefString.size());
+}
+
+void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
+  // When method is a synthesized one, such as a getter/setter there is
+  // nothing to rewrite.
+  if (Method->isSynthesized())
+    return;
+  SourceLocation LocStart = Method->getLocStart();
+  SourceLocation LocEnd = Method->getLocEnd();
+
+  if (SM->getInstantiationLineNumber(LocEnd) >
+      SM->getInstantiationLineNumber(LocStart)) {
+    InsertText(LocStart, "#if 0\n", 6);
+    ReplaceText(LocEnd, 1, ";\n#endif\n", 9);
+  } else {
+    InsertText(LocStart, "// ", 3);
+  }
+}
+
+void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
+  SourceLocation Loc = prop->getAtLoc();
+
+  ReplaceText(Loc, 0, "// ", 3);
+  // FIXME: handle properties that are declared across multiple lines.
+}
+
+void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
+  SourceLocation LocStart = CatDecl->getLocStart();
+
+  // FIXME: handle category headers that are declared across multiple lines.
+  ReplaceText(LocStart, 0, "// ", 3);
+
+  for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
+       E = CatDecl->prop_end(); I != E; ++I)
+    RewriteProperty(*I);
+  
+  for (ObjCCategoryDecl::instmeth_iterator
+         I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
+       I != E; ++I)
+    RewriteMethodDeclaration(*I);
+  for (ObjCCategoryDecl::classmeth_iterator
+         I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
+       I != E; ++I)
+    RewriteMethodDeclaration(*I);
+
+  // Lastly, comment out the @end.
+  ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// ", 3);
+}
+
+void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
+  std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
+
+  SourceLocation LocStart = PDecl->getLocStart();
+
+  // FIXME: handle protocol headers that are declared across multiple lines.
+  ReplaceText(LocStart, 0, "// ", 3);
+
+  for (ObjCProtocolDecl::instmeth_iterator
+         I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
+       I != E; ++I)
+    RewriteMethodDeclaration(*I);
+  for (ObjCProtocolDecl::classmeth_iterator
+         I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+       I != E; ++I)
+    RewriteMethodDeclaration(*I);
+
+  // Lastly, comment out the @end.
+  SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
+  ReplaceText(LocEnd, 0, "// ", 3);
+
+  // Must comment out @optional/@required
+  const char *startBuf = SM->getCharacterData(LocStart);
+  const char *endBuf = SM->getCharacterData(LocEnd);
+  for (const char *p = startBuf; p < endBuf; p++) {
+    if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
+      std::string CommentedOptional = "/* @optional */";
+      SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
+      ReplaceText(OptionalLoc, strlen("@optional"),
+                  CommentedOptional.c_str(), CommentedOptional.size());
+
+    }
+    else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
+      std::string CommentedRequired = "/* @required */";
+      SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
+      ReplaceText(OptionalLoc, strlen("@required"),
+                  CommentedRequired.c_str(), CommentedRequired.size());
+
+    }
+  }
+}
+
+void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) {
+  SourceLocation LocStart = PDecl->getLocation();
+  if (LocStart.isInvalid())
+    assert(false && "Invalid SourceLocation");
+  // FIXME: handle forward protocol that are declared across multiple lines.
+  ReplaceText(LocStart, 0, "// ", 3);
+}
+
+void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
+                                        std::string &ResultStr) {
+  //fprintf(stderr,"In RewriteObjCMethodDecl\n");
+  const FunctionType *FPRetType = 0;
+  ResultStr += "\nstatic ";
+  if (OMD->getResultType()->isObjCQualifiedIdType())
+    ResultStr += "id";
+  else if (OMD->getResultType()->isFunctionPointerType() ||
+           OMD->getResultType()->isBlockPointerType()) {
+    // needs special handling, since pointer-to-functions have special
+    // syntax (where a decaration models use).
+    QualType retType = OMD->getResultType();
+    QualType PointeeTy;
+    if (const PointerType* PT = retType->getAs<PointerType>())
+      PointeeTy = PT->getPointeeType();
+    else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
+      PointeeTy = BPT->getPointeeType();
+    if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
+      ResultStr += FPRetType->getResultType().getAsString();
+      ResultStr += "(*";
+    }
+  } else
+    ResultStr += OMD->getResultType().getAsString();
+  ResultStr += " ";
+
+  // Unique method name
+  std::string NameStr;
+
+  if (OMD->isInstanceMethod())
+    NameStr += "_I_";
+  else
+    NameStr += "_C_";
+
+  NameStr += OMD->getClassInterface()->getNameAsString();
+  NameStr += "_";
+
+  if (ObjCCategoryImplDecl *CID =
+      dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
+    NameStr += CID->getNameAsString();
+    NameStr += "_";
+  }
+  // Append selector names, replacing ':' with '_'
+  {
+    std::string selString = OMD->getSelector().getAsString();
+    int len = selString.size();
+    for (int i = 0; i < len; i++)
+      if (selString[i] == ':')
+        selString[i] = '_';
+    NameStr += selString;
+  }
+  // Remember this name for metadata emission
+  MethodInternalNames[OMD] = NameStr;
+  ResultStr += NameStr;
+
+  // Rewrite arguments
+  ResultStr += "(";
+
+  // invisible arguments
+  if (OMD->isInstanceMethod()) {
+    QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface());
+    selfTy = Context->getPointerType(selfTy);
+    if (!LangOpts.Microsoft) {
+      if (ObjCSynthesizedStructs.count(OMD->getClassInterface()))
+        ResultStr += "struct ";
+    }
+    // When rewriting for Microsoft, explicitly omit the structure name.
+    ResultStr += OMD->getClassInterface()->getNameAsString();
+    ResultStr += " *";
+  }
+  else
+    ResultStr += Context->getObjCClassType().getAsString();
+
+  ResultStr += " self, ";
+  ResultStr += Context->getObjCSelType().getAsString();
+  ResultStr += " _cmd";
+
+  // Method arguments.
+  for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+       E = OMD->param_end(); PI != E; ++PI) {
+    ParmVarDecl *PDecl = *PI;
+    ResultStr += ", ";
+    if (PDecl->getType()->isObjCQualifiedIdType()) {
+      ResultStr += "id ";
+      ResultStr += PDecl->getNameAsString();
+    } else {
+      std::string Name = PDecl->getNameAsString();
+      if (isTopLevelBlockPointerType(PDecl->getType())) {
+        // Make sure we convert "t (^)(...)" to "t (*)(...)".
+        const BlockPointerType *BPT = PDecl->getType()->getAs<BlockPointerType>();
+        Context->getPointerType(BPT->getPointeeType()).getAsStringInternal(Name,
+                                                        Context->PrintingPolicy);
+      } else
+        PDecl->getType().getAsStringInternal(Name, Context->PrintingPolicy);
+      ResultStr += Name;
+    }
+  }
+  if (OMD->isVariadic())
+    ResultStr += ", ...";
+  ResultStr += ") ";
+
+  if (FPRetType) {
+    ResultStr += ")"; // close the precedence "scope" for "*".
+
+    // Now, emit the argument types (if any).
+    if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
+      ResultStr += "(";
+      for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+        if (i) ResultStr += ", ";
+        std::string ParamStr = FT->getArgType(i).getAsString();
+        ResultStr += ParamStr;
+      }
+      if (FT->isVariadic()) {
+        if (FT->getNumArgs()) ResultStr += ", ";
+        ResultStr += "...";
+      }
+      ResultStr += ")";
+    } else {
+      ResultStr += "()";
+    }
+  }
+}
+void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
+  ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
+  ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
+
+  if (IMD)
+    InsertText(IMD->getLocStart(), "// ", 3);
+  else
+    InsertText(CID->getLocStart(), "// ", 3);
+
+  for (ObjCCategoryImplDecl::instmeth_iterator
+       I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(),
+       E = IMD ? IMD->instmeth_end() : CID->instmeth_end();
+       I != E; ++I) {
+    std::string ResultStr;
+    ObjCMethodDecl *OMD = *I;
+    RewriteObjCMethodDecl(OMD, ResultStr);
+    SourceLocation LocStart = OMD->getLocStart();
+    SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+
+    const char *startBuf = SM->getCharacterData(LocStart);
+    const char *endBuf = SM->getCharacterData(LocEnd);
+    ReplaceText(LocStart, endBuf-startBuf,
+                ResultStr.c_str(), ResultStr.size());
+  }
+
+  for (ObjCCategoryImplDecl::classmeth_iterator
+       I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(),
+       E = IMD ? IMD->classmeth_end() : CID->classmeth_end();
+       I != E; ++I) {
+    std::string ResultStr;
+    ObjCMethodDecl *OMD = *I;
+    RewriteObjCMethodDecl(OMD, ResultStr);
+    SourceLocation LocStart = OMD->getLocStart();
+    SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+
+    const char *startBuf = SM->getCharacterData(LocStart);
+    const char *endBuf = SM->getCharacterData(LocEnd);
+    ReplaceText(LocStart, endBuf-startBuf,
+                ResultStr.c_str(), ResultStr.size());
+  }
+  for (ObjCCategoryImplDecl::propimpl_iterator
+       I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(),
+       E = IMD ? IMD->propimpl_end() : CID->propimpl_end();
+       I != E; ++I) {
+    RewritePropertyImplDecl(*I, IMD, CID);
+  }
+
+  if (IMD)
+    InsertText(IMD->getLocEnd(), "// ", 3);
+  else
+   InsertText(CID->getLocEnd(), "// ", 3);
+}
+
+void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
+  std::string ResultStr;
+  if (!ObjCForwardDecls.count(ClassDecl)) {
+    // we haven't seen a forward decl - generate a typedef.
+    ResultStr = "#ifndef _REWRITER_typedef_";
+    ResultStr += ClassDecl->getNameAsString();
+    ResultStr += "\n";
+    ResultStr += "#define _REWRITER_typedef_";
+    ResultStr += ClassDecl->getNameAsString();
+    ResultStr += "\n";
+    ResultStr += "typedef struct objc_object ";
+    ResultStr += ClassDecl->getNameAsString();
+    ResultStr += ";\n#endif\n";
+    // Mark this typedef as having been generated.
+    ObjCForwardDecls.insert(ClassDecl);
+  }
+  SynthesizeObjCInternalStruct(ClassDecl, ResultStr);
+
+  for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(),
+         E = ClassDecl->prop_end(); I != E; ++I)
+    RewriteProperty(*I);
+  for (ObjCInterfaceDecl::instmeth_iterator
+         I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end();
+       I != E; ++I)
+    RewriteMethodDeclaration(*I);
+  for (ObjCInterfaceDecl::classmeth_iterator
+         I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end();
+       I != E; ++I)
+    RewriteMethodDeclaration(*I);
+
+  // Lastly, comment out the @end.
+  ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// ", 3);
+}
+
+Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+                                         SourceRange SrcRange) {
+  // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
+  // This allows us to reuse all the fun and games in SynthMessageExpr().
+  ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS());
+  ObjCMessageExpr *MsgExpr;
+  ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
+  llvm::SmallVector<Expr *, 1> ExprVec;
+  ExprVec.push_back(newStmt);
+
+  Stmt *Receiver = PropRefExpr->getBase();
+  ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
+  if (PRE && PropGetters[PRE]) {
+    // This allows us to handle chain/nested property getters.
+    Receiver = PropGetters[PRE];
+  }
+  MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver),
+                                PDecl->getSetterName(), PDecl->getType(),
+                                PDecl->getSetterMethodDecl(),
+                                SourceLocation(), SourceLocation(),
+                                &ExprVec[0], 1);
+  Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
+
+  // Now do the actual rewrite.
+  ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
+  //delete BinOp;
+  // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
+  // to things that stay around.
+  Context->Deallocate(MsgExpr);
+  return ReplacingStmt;
+}
+
+Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) {
+  // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
+  // This allows us to reuse all the fun and games in SynthMessageExpr().
+  ObjCMessageExpr *MsgExpr;
+  ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
+
+  Stmt *Receiver = PropRefExpr->getBase();
+
+  ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
+  if (PRE && PropGetters[PRE]) {
+    // This allows us to handle chain/nested property getters.
+    Receiver = PropGetters[PRE];
+  }
+  MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver),
+                                PDecl->getGetterName(), PDecl->getType(),
+                                PDecl->getGetterMethodDecl(),
+                                SourceLocation(), SourceLocation(),
+                                0, 0);
+
+  Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
+
+  if (!PropParentMap)
+    PropParentMap = new ParentMap(CurrentBody);
+
+  Stmt *Parent = PropParentMap->getParent(PropRefExpr);
+  if (Parent && isa<ObjCPropertyRefExpr>(Parent)) {
+    // We stash away the ReplacingStmt since actually doing the
+    // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
+    PropGetters[PropRefExpr] = ReplacingStmt;
+    // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
+    // to things that stay around.
+    Context->Deallocate(MsgExpr);
+    return PropRefExpr; // return the original...
+  } else {
+    ReplaceStmt(PropRefExpr, ReplacingStmt);
+    // delete PropRefExpr; elsewhere...
+    // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
+    // to things that stay around.
+    Context->Deallocate(MsgExpr);
+    return ReplacingStmt;
+  }
+}
+
+Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
+                                          SourceLocation OrigStart,
+                                          bool &replaced) {
+  ObjCIvarDecl *D = IV->getDecl();
+  const Expr *BaseExpr = IV->getBase();
+  if (CurMethodDef) {
+    if (BaseExpr->getType()->isObjCObjectPointerType()) {
+      ObjCInterfaceType *iFaceDecl =
+        dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
+      assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
+      // lookup which class implements the instance variable.
+      ObjCInterfaceDecl *clsDeclared = 0;
+      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
+                                                   clsDeclared);
+      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
+
+      // Synthesize an explicit cast to gain access to the ivar.
+      std::string RecName = clsDeclared->getIdentifier()->getName();
+      RecName += "_IMPL";
+      IdentifierInfo *II = &Context->Idents.get(RecName.c_str());
+      RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                          SourceLocation(), II);
+      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
+      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+                                                    CastExpr::CK_Unknown,
+                                                    IV->getBase());
+      // Don't forget the parens to enforce the proper binding.
+      ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
+                                               IV->getBase()->getLocEnd(),
+                                               castExpr);
+      replaced = true;
+      if (IV->isFreeIvar() &&
+          CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
+        MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
+                                                   IV->getLocation(),
+                                                   D->getType());
+        // delete IV; leak for now, see RewritePropertySetter() usage for more info.
+        return ME;
+      }
+      // Get the new text
+      // Cannot delete IV->getBase(), since PE points to it.
+      // Replace the old base with the cast. This is important when doing
+      // embedded rewrites. For example, [newInv->_container addObject:0].
+      IV->setBase(PE);
+      return IV;
+    }
+  } else { // we are outside a method.
+    assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
+
+    // Explicit ivar refs need to have a cast inserted.
+    // FIXME: consider sharing some of this code with the code above.
+    if (BaseExpr->getType()->isObjCObjectPointerType()) {
+      ObjCInterfaceType *iFaceDecl =
+        dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
+      // lookup which class implements the instance variable.
+      ObjCInterfaceDecl *clsDeclared = 0;
+      iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
+                                                   clsDeclared);
+      assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
+
+      // Synthesize an explicit cast to gain access to the ivar.
+      std::string RecName = clsDeclared->getIdentifier()->getName();
+      RecName += "_IMPL";
+      IdentifierInfo *II = &Context->Idents.get(RecName.c_str());
+      RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                          SourceLocation(), II);
+      assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
+      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+      CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+                                                    CastExpr::CK_Unknown,
+                                                    IV->getBase());
+      // Don't forget the parens to enforce the proper binding.
+      ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
+                                    IV->getBase()->getLocEnd(), castExpr);
+      replaced = true;
+      // Cannot delete IV->getBase(), since PE points to it.
+      // Replace the old base with the cast. This is important when doing
+      // embedded rewrites. For example, [newInv->_container addObject:0].
+      IV->setBase(PE);
+      return IV;
+    }
+  }
+  return IV;
+}
+
+Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI) {
+    if (*CI) {
+      Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);
+      if (newStmt)
+        *CI = newStmt;
+    }
+  }
+  if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
+    SourceRange OrigStmtRange = S->getSourceRange();
+    Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(),
+                                           replaced);
+    return newStmt;
+  } 
+  if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) {
+    Stmt *newStmt = SynthMessageExpr(MsgRefExpr);
+    return newStmt;
+  }
+  return S;
+}
+
+/// SynthCountByEnumWithState - To print:
+/// ((unsigned int (*)
+///  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
+///  (void *)objc_msgSend)((id)l_collection,
+///                        sel_registerName(
+///                          "countByEnumeratingWithState:objects:count:"),
+///                        &enumState,
+///                        (id *)items, (unsigned int)16)
+///
+void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
+  buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
+  "id *, unsigned int))(void *)objc_msgSend)";
+  buf += "\n\t\t";
+  buf += "((id)l_collection,\n\t\t";
+  buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
+  buf += "\n\t\t";
+  buf += "&enumState, "
+         "(id *)items, (unsigned int)16)";
+}
+
+/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
+/// statement to exit to its outer synthesized loop.
+///
+Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
+  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+    return S;
+  // replace break with goto __break_label
+  std::string buf;
+
+  SourceLocation startLoc = S->getLocStart();
+  buf = "goto __break_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  ReplaceText(startLoc, strlen("break"), buf.c_str(), buf.size());
+
+  return 0;
+}
+
+/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
+/// statement to continue with its inner synthesized loop.
+///
+Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
+  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+    return S;
+  // replace continue with goto __continue_label
+  std::string buf;
+
+  SourceLocation startLoc = S->getLocStart();
+  buf = "goto __continue_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size());
+
+  return 0;
+}
+
+/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
+///  It rewrites:
+/// for ( type elem in collection) { stmts; }
+
+/// Into:
+/// {
+///   type elem;
+///   struct __objcFastEnumerationState enumState = { 0 };
+///   id items[16];
+///   id l_collection = (id)collection;
+///   unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
+///                                       objects:items count:16];
+/// if (limit) {
+///   unsigned long startMutations = *enumState.mutationsPtr;
+///   do {
+///        unsigned long counter = 0;
+///        do {
+///             if (startMutations != *enumState.mutationsPtr)
+///               objc_enumerationMutation(l_collection);
+///             elem = (type)enumState.itemsPtr[counter++];
+///             stmts;
+///             __continue_label: ;
+///        } while (counter < limit);
+///   } while (limit = [l_collection countByEnumeratingWithState:&enumState
+///                                  objects:items count:16]);
+///   elem = nil;
+///   __break_label: ;
+///  }
+///  else
+///       elem = nil;
+///  }
+///
+Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
+                                                SourceLocation OrigEnd) {
+  assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
+  assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
+         "ObjCForCollectionStmt Statement stack mismatch");
+  assert(!ObjCBcLabelNo.empty() &&
+         "ObjCForCollectionStmt - Label No stack empty");
+
+  SourceLocation startLoc = S->getLocStart();
+  const char *startBuf = SM->getCharacterData(startLoc);
+  const char *elementName;
+  std::string elementTypeAsString;
+  std::string buf;
+  buf = "\n{\n\t";
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
+    // type elem;
+    NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
+    QualType ElementType = cast<ValueDecl>(D)->getType();
+    if (ElementType->isObjCQualifiedIdType() ||
+        ElementType->isObjCQualifiedInterfaceType())
+      // Simply use 'id' for all qualified types.
+      elementTypeAsString = "id";
+    else
+      elementTypeAsString = ElementType.getAsString();
+    buf += elementTypeAsString;
+    buf += " ";
+    elementName = D->getNameAsCString();
+    buf += elementName;
+    buf += ";\n\t";
+  }
+  else {
+    DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
+    elementName = DR->getDecl()->getNameAsCString();
+    ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
+    if (VD->getType()->isObjCQualifiedIdType() ||
+        VD->getType()->isObjCQualifiedInterfaceType())
+      // Simply use 'id' for all qualified types.
+      elementTypeAsString = "id";
+    else
+      elementTypeAsString = VD->getType().getAsString();
+  }
+
+  // struct __objcFastEnumerationState enumState = { 0 };
+  buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
+  // id items[16];
+  buf += "id items[16];\n\t";
+  // id l_collection = (id)
+  buf += "id l_collection = (id)";
+  // Find start location of 'collection' the hard way!
+  const char *startCollectionBuf = startBuf;
+  startCollectionBuf += 3;  // skip 'for'
+  startCollectionBuf = strchr(startCollectionBuf, '(');
+  startCollectionBuf++; // skip '('
+  // find 'in' and skip it.
+  while (*startCollectionBuf != ' ' ||
+         *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
+         (*(startCollectionBuf+3) != ' ' &&
+          *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
+    startCollectionBuf++;
+  startCollectionBuf += 3;
+
+  // Replace: "for (type element in" with string constructed thus far.
+  ReplaceText(startLoc, startCollectionBuf - startBuf,
+              buf.c_str(), buf.size());
+  // Replace ')' in for '(' type elem in collection ')' with ';'
+  SourceLocation rightParenLoc = S->getRParenLoc();
+  const char *rparenBuf = SM->getCharacterData(rightParenLoc);
+  SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf);
+  buf = ";\n\t";
+
+  // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
+  //                                   objects:items count:16];
+  // which is synthesized into:
+  // unsigned int limit =
+  // ((unsigned int (*)
+  //  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
+  //  (void *)objc_msgSend)((id)l_collection,
+  //                        sel_registerName(
+  //                          "countByEnumeratingWithState:objects:count:"),
+  //                        (struct __objcFastEnumerationState *)&state,
+  //                        (id *)items, (unsigned int)16);
+  buf += "unsigned long limit =\n\t\t";
+  SynthCountByEnumWithState(buf);
+  buf += ";\n\t";
+  /// if (limit) {
+  ///   unsigned long startMutations = *enumState.mutationsPtr;
+  ///   do {
+  ///        unsigned long counter = 0;
+  ///        do {
+  ///             if (startMutations != *enumState.mutationsPtr)
+  ///               objc_enumerationMutation(l_collection);
+  ///             elem = (type)enumState.itemsPtr[counter++];
+  buf += "if (limit) {\n\t";
+  buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
+  buf += "do {\n\t\t";
+  buf += "unsigned long counter = 0;\n\t\t";
+  buf += "do {\n\t\t\t";
+  buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
+  buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
+  buf += elementName;
+  buf += " = (";
+  buf += elementTypeAsString;
+  buf += ")enumState.itemsPtr[counter++];";
+  // Replace ')' in for '(' type elem in collection ')' with all of these.
+  ReplaceText(lparenLoc, 1, buf.c_str(), buf.size());
+
+  ///            __continue_label: ;
+  ///        } while (counter < limit);
+  ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState
+  ///                                  objects:items count:16]);
+  ///   elem = nil;
+  ///   __break_label: ;
+  ///  }
+  ///  else
+  ///       elem = nil;
+  ///  }
+  ///
+  buf = ";\n\t";
+  buf += "__continue_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  buf += ": ;";
+  buf += "\n\t\t";
+  buf += "} while (counter < limit);\n\t";
+  buf += "} while (limit = ";
+  SynthCountByEnumWithState(buf);
+  buf += ");\n\t";
+  buf += elementName;
+  buf += " = ((";
+  buf += elementTypeAsString;
+  buf += ")0);\n\t";
+  buf += "__break_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  buf += ": ;\n\t";
+  buf += "}\n\t";
+  buf += "else\n\t\t";
+  buf += elementName;
+  buf += " = ((";
+  buf += elementTypeAsString;
+  buf += ")0);\n\t";
+  buf += "}\n";
+
+  // Insert all these *after* the statement body.
+  // FIXME: If this should support Obj-C++, support CXXTryStmt
+  if (isa<CompoundStmt>(S->getBody())) {
+    SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1);
+    InsertText(endBodyLoc, buf.c_str(), buf.size());
+  } else {
+    /* Need to treat single statements specially. For example:
+     *
+     *     for (A *a in b) if (stuff()) break;
+     *     for (A *a in b) xxxyy;
+     *
+     * The following code simply scans ahead to the semi to find the actual end.
+     */
+    const char *stmtBuf = SM->getCharacterData(OrigEnd);
+    const char *semiBuf = strchr(stmtBuf, ';');
+    assert(semiBuf && "Can't find ';'");
+    SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1);
+    InsertText(endBodyLoc, buf.c_str(), buf.size());
+  }
+  Stmts.pop_back();
+  ObjCBcLabelNo.pop_back();
+  return 0;
+}
+
+/// RewriteObjCSynchronizedStmt -
+/// This routine rewrites @synchronized(expr) stmt;
+/// into:
+/// objc_sync_enter(expr);
+/// @try stmt @finally { objc_sync_exit(expr); }
+///
+Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+  // Get the start location and compute the semi location.
+  SourceLocation startLoc = S->getLocStart();
+  const char *startBuf = SM->getCharacterData(startLoc);
+
+  assert((*startBuf == '@') && "bogus @synchronized location");
+
+  std::string buf;
+  buf = "objc_sync_enter((id)";
+  const char *lparenBuf = startBuf;
+  while (*lparenBuf != '(') lparenBuf++;
+  ReplaceText(startLoc, lparenBuf-startBuf+1, buf.c_str(), buf.size());
+  // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
+  // the sync expression is typically a message expression that's already
+  // been rewritten! (which implies the SourceLocation's are invalid).
+  SourceLocation endLoc = S->getSynchBody()->getLocStart();
+  const char *endBuf = SM->getCharacterData(endLoc);
+  while (*endBuf != ')') endBuf--;
+  SourceLocation rparenLoc = startLoc.getFileLocWithOffset(endBuf-startBuf);
+  buf = ");\n";
+  // declare a new scope with two variables, _stack and _rethrow.
+  buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
+  buf += "int buf[18/*32-bit i386*/];\n";
+  buf += "char *pointers[4];} _stack;\n";
+  buf += "id volatile _rethrow = 0;\n";
+  buf += "objc_exception_try_enter(&_stack);\n";
+  buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
+  ReplaceText(rparenLoc, 1, buf.c_str(), buf.size());
+  startLoc = S->getSynchBody()->getLocEnd();
+  startBuf = SM->getCharacterData(startLoc);
+
+  assert((*startBuf == '}') && "bogus @synchronized block");
+  SourceLocation lastCurlyLoc = startLoc;
+  buf = "}\nelse {\n";
+  buf += "  _rethrow = objc_exception_extract(&_stack);\n";
+  buf += "}\n";
+  buf += "{ /* implicit finally clause */\n";
+  buf += "  if (!_rethrow) objc_exception_try_exit(&_stack);\n";
+  
+  std::string syncBuf;
+  syncBuf += " objc_sync_exit(";
+  Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+                                            CastExpr::CK_Unknown,
+                                            S->getSynchExpr());
+  std::string syncExprBufS;
+  llvm::raw_string_ostream syncExprBuf(syncExprBufS);
+  syncExpr->printPretty(syncExprBuf, *Context, 0,
+                        PrintingPolicy(LangOpts));
+  syncBuf += syncExprBuf.str();
+  syncBuf += ");";
+  
+  buf += syncBuf;
+  buf += "\n  if (_rethrow) objc_exception_throw(_rethrow);\n";
+  buf += "}\n";
+  buf += "}";
+
+  ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+
+  bool hasReturns = false;
+  HasReturnStmts(S->getSynchBody(), hasReturns);
+  if (hasReturns)
+    RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
+
+  return 0;
+}
+
+void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
+{
+  // Perform a bottom up traversal of all children.
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI)
+      WarnAboutReturnGotoStmts(*CI);
+
+  if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
+    Diags.Report(Context->getFullLoc(S->getLocStart()),
+                 TryFinallyContainsReturnDiag);
+  }
+  return;
+}
+
+void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 
+{  
+  // Perform a bottom up traversal of all children.
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+        CI != E; ++CI)
+   if (*CI)
+     HasReturnStmts(*CI, hasReturns);
+
+ if (isa<ReturnStmt>(S))
+   hasReturns = true;
+ return;
+}
+
+void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+      CI != E; ++CI)
+   if (*CI) {
+     RewriteTryReturnStmts(*CI);
+   }
+ if (isa<ReturnStmt>(S)) {
+   SourceLocation startLoc = S->getLocStart();
+   const char *startBuf = SM->getCharacterData(startLoc);
+
+   const char *semiBuf = strchr(startBuf, ';');
+   assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
+   SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+   std::string buf;
+   buf = "{ objc_exception_try_exit(&_stack); return";
+   
+   ReplaceText(startLoc, 6, buf.c_str(), buf.size());
+   InsertText(onePastSemiLoc, "}", 1);
+ }
+ return;
+}
+
+void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
+  // Perform a bottom up traversal of all children.
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI) {
+      RewriteSyncReturnStmts(*CI, syncExitBuf);
+    }
+  if (isa<ReturnStmt>(S)) {
+    SourceLocation startLoc = S->getLocStart();
+    const char *startBuf = SM->getCharacterData(startLoc);
+
+    const char *semiBuf = strchr(startBuf, ';');
+    assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
+    SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+    std::string buf;
+    buf = "{ objc_exception_try_exit(&_stack);";
+    buf += syncExitBuf;
+    buf += " return";
+    
+    ReplaceText(startLoc, 6, buf.c_str(), buf.size());
+    InsertText(onePastSemiLoc, "}", 1);
+  }
+  return;
+}
+
+Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
+  // Get the start location and compute the semi location.
+  SourceLocation startLoc = S->getLocStart();
+  const char *startBuf = SM->getCharacterData(startLoc);
+
+  assert((*startBuf == '@') && "bogus @try location");
+
+  std::string buf;
+  // declare a new scope with two variables, _stack and _rethrow.
+  buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
+  buf += "int buf[18/*32-bit i386*/];\n";
+  buf += "char *pointers[4];} _stack;\n";
+  buf += "id volatile _rethrow = 0;\n";
+  buf += "objc_exception_try_enter(&_stack);\n";
+  buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
+
+  ReplaceText(startLoc, 4, buf.c_str(), buf.size());
+
+  startLoc = S->getTryBody()->getLocEnd();
+  startBuf = SM->getCharacterData(startLoc);
+
+  assert((*startBuf == '}') && "bogus @try block");
+
+  SourceLocation lastCurlyLoc = startLoc;
+  ObjCAtCatchStmt *catchList = S->getCatchStmts();
+  if (catchList) {
+    startLoc = startLoc.getFileLocWithOffset(1);
+    buf = " /* @catch begin */ else {\n";
+    buf += " id _caught = objc_exception_extract(&_stack);\n";
+    buf += " objc_exception_try_enter (&_stack);\n";
+    buf += " if (_setjmp(_stack.buf))\n";
+    buf += "   _rethrow = objc_exception_extract(&_stack);\n";
+    buf += " else { /* @catch continue */";
+
+    InsertText(startLoc, buf.c_str(), buf.size());
+  } else { /* no catch list */
+    buf = "}\nelse {\n";
+    buf += "  _rethrow = objc_exception_extract(&_stack);\n";
+    buf += "}";
+    ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+  }
+  bool sawIdTypedCatch = false;
+  Stmt *lastCatchBody = 0;
+  while (catchList) {
+    ParmVarDecl *catchDecl = catchList->getCatchParamDecl();
+
+    if (catchList == S->getCatchStmts())
+      buf = "if ("; // we are generating code for the first catch clause
+    else
+      buf = "else if (";
+    startLoc = catchList->getLocStart();
+    startBuf = SM->getCharacterData(startLoc);
+
+    assert((*startBuf == '@') && "bogus @catch location");
+
+    const char *lParenLoc = strchr(startBuf, '(');
+
+    if (catchList->hasEllipsis()) {
+      // Now rewrite the body...
+      lastCatchBody = catchList->getCatchBody();
+      SourceLocation bodyLoc = lastCatchBody->getLocStart();
+      const char *bodyBuf = SM->getCharacterData(bodyLoc);
+      assert(*SM->getCharacterData(catchList->getRParenLoc()) == ')' &&
+             "bogus @catch paren location");
+      assert((*bodyBuf == '{') && "bogus @catch body location");
+
+      buf += "1) { id _tmp = _caught;";
+      Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
+    } else if (catchDecl) {
+      QualType t = catchDecl->getType();
+      if (t == Context->getObjCIdType()) {
+        buf += "1) { ";
+        ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
+        sawIdTypedCatch = true;
+      } else if (t->isObjCObjectPointerType()) {
+        QualType InterfaceTy = t->getPointeeType();
+        const ObjCInterfaceType *cls = // Should be a pointer to a class.
+          InterfaceTy->getAs<ObjCInterfaceType>();
+        if (cls) {
+          buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
+          buf += cls->getDecl()->getNameAsString();
+          buf += "\"), (struct objc_object *)_caught)) { ";
+          ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
+        }
+      }
+      // Now rewrite the body...
+      lastCatchBody = catchList->getCatchBody();
+      SourceLocation rParenLoc = catchList->getRParenLoc();
+      SourceLocation bodyLoc = lastCatchBody->getLocStart();
+      const char *bodyBuf = SM->getCharacterData(bodyLoc);
+      const char *rParenBuf = SM->getCharacterData(rParenLoc);
+      assert((*rParenBuf == ')') && "bogus @catch paren location");
+      assert((*bodyBuf == '{') && "bogus @catch body location");
+
+      buf = " = _caught;";
+      // Here we replace ") {" with "= _caught;" (which initializes and
+      // declares the @catch parameter).
+      ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size());
+    } else {
+      assert(false && "@catch rewrite bug");
+    }
+    // make sure all the catch bodies get rewritten!
+    catchList = catchList->getNextCatchStmt();
+  }
+  // Complete the catch list...
+  if (lastCatchBody) {
+    SourceLocation bodyLoc = lastCatchBody->getLocEnd();
+    assert(*SM->getCharacterData(bodyLoc) == '}' &&
+           "bogus @catch body location");
+
+    // Insert the last (implicit) else clause *before* the right curly brace.
+    bodyLoc = bodyLoc.getFileLocWithOffset(-1);
+    buf = "} /* last catch end */\n";
+    buf += "else {\n";
+    buf += " _rethrow = _caught;\n";
+    buf += " objc_exception_try_exit(&_stack);\n";
+    buf += "} } /* @catch end */\n";
+    if (!S->getFinallyStmt())
+      buf += "}\n";
+    InsertText(bodyLoc, buf.c_str(), buf.size());
+
+    // Set lastCurlyLoc
+    lastCurlyLoc = lastCatchBody->getLocEnd();
+  }
+  if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
+    startLoc = finalStmt->getLocStart();
+    startBuf = SM->getCharacterData(startLoc);
+    assert((*startBuf == '@') && "bogus @finally start");
+
+    buf = "/* @finally */";
+    ReplaceText(startLoc, 8, buf.c_str(), buf.size());
+
+    Stmt *body = finalStmt->getFinallyBody();
+    SourceLocation startLoc = body->getLocStart();
+    SourceLocation endLoc = body->getLocEnd();
+    assert(*SM->getCharacterData(startLoc) == '{' &&
+           "bogus @finally body location");
+    assert(*SM->getCharacterData(endLoc) == '}' &&
+           "bogus @finally body location");
+
+    startLoc = startLoc.getFileLocWithOffset(1);
+    buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
+    InsertText(startLoc, buf.c_str(), buf.size());
+    endLoc = endLoc.getFileLocWithOffset(-1);
+    buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
+    InsertText(endLoc, buf.c_str(), buf.size());
+
+    // Set lastCurlyLoc
+    lastCurlyLoc = body->getLocEnd();
+
+    // Now check for any return/continue/go statements within the @try.
+    WarnAboutReturnGotoStmts(S->getTryBody());
+  } else { /* no finally clause - make sure we synthesize an implicit one */
+    buf = "{ /* implicit finally clause */\n";
+    buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
+    buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
+    buf += "}";
+    ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+    
+    // Now check for any return/continue/go statements within the @try.
+    // The implicit finally clause won't called if the @try contains any
+    // jump statements.
+    bool hasReturns = false;
+    HasReturnStmts(S->getTryBody(), hasReturns);
+    if (hasReturns)
+      RewriteTryReturnStmts(S->getTryBody());
+  }
+  // Now emit the final closing curly brace...
+  lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
+  buf = " } /* @try scope end */\n";
+  InsertText(lastCurlyLoc, buf.c_str(), buf.size());
+  return 0;
+}
+
+Stmt *RewriteObjC::RewriteObjCCatchStmt(ObjCAtCatchStmt *S) {
+  return 0;
+}
+
+Stmt *RewriteObjC::RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S) {
+  return 0;
+}
+
+// This can't be done with ReplaceStmt(S, ThrowExpr), since
+// the throw expression is typically a message expression that's already
+// been rewritten! (which implies the SourceLocation's are invalid).
+Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
+  // Get the start location and compute the semi location.
+  SourceLocation startLoc = S->getLocStart();
+  const char *startBuf = SM->getCharacterData(startLoc);
+
+  assert((*startBuf == '@') && "bogus @throw location");
+
+  std::string buf;
+  /* void objc_exception_throw(id) __attribute__((noreturn)); */
+  if (S->getThrowExpr())
+    buf = "objc_exception_throw(";
+  else // add an implicit argument
+    buf = "objc_exception_throw(_caught";
+
+  // handle "@  throw" correctly.
+  const char *wBuf = strchr(startBuf, 'w');
+  assert((*wBuf == 'w') && "@throw: can't find 'w'");
+  ReplaceText(startLoc, wBuf-startBuf+1, buf.c_str(), buf.size());
+
+  const char *semiBuf = strchr(startBuf, ';');
+  assert((*semiBuf == ';') && "@throw: can't find ';'");
+  SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
+  buf = ");";
+  ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
+  return 0;
+}
+
+Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
+  // Create a new string expression.
+  QualType StrType = Context->getPointerType(Context->CharTy);
+  std::string StrEncoding;
+  Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
+  Expr *Replacement = StringLiteral::Create(*Context,StrEncoding.c_str(),
+                                            StrEncoding.length(), false,StrType,
+                                            SourceLocation());
+  ReplaceStmt(Exp, Replacement);
+
+  // Replace this subexpr in the parent.
+  // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+  return Replacement;
+}
+
+Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
+  if (!SelGetUidFunctionDecl)
+    SynthSelGetUidFunctionDecl();
+  assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
+  // Create a call to sel_registerName("selName").
+  llvm::SmallVector<Expr*, 8> SelExprs;
+  QualType argType = Context->getPointerType(Context->CharTy);
+  SelExprs.push_back(StringLiteral::Create(*Context,
+                                       Exp->getSelector().getAsString().c_str(),
+                                       Exp->getSelector().getAsString().size(),
+                                       false, argType, SourceLocation()));
+  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
+                                                 &SelExprs[0], SelExprs.size());
+  ReplaceStmt(Exp, SelExp);
+  // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+  return SelExp;
+}
+
+CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
+  FunctionDecl *FD, Expr **args, unsigned nargs) {
+  // Get the type, we will need to reference it in a couple spots.
+  QualType msgSendType = FD->getType();
+
+  // Create a reference to the objc_msgSend() declaration.
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, msgSendType, SourceLocation());
+
+  // Now, we cast the reference to a pointer to the objc_msgSend type.
+  QualType pToFunc = Context->getPointerType(msgSendType);
+  ImplicitCastExpr *ICE = new (Context) ImplicitCastExpr(pToFunc,
+                                                         CastExpr::CK_Unknown,
+                                                         DRE,
+                                               /*isLvalue=*/false);
+
+  const FunctionType *FT = msgSendType->getAs<FunctionType>();
+
+  return new (Context) CallExpr(*Context, ICE, args, nargs, FT->getResultType(),
+                                SourceLocation());
+}
+
+static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
+                                const char *&startRef, const char *&endRef) {
+  while (startBuf < endBuf) {
+    if (*startBuf == '<')
+      startRef = startBuf; // mark the start.
+    if (*startBuf == '>') {
+      if (startRef && *startRef == '<') {
+        endRef = startBuf; // mark the end.
+        return true;
+      }
+      return false;
+    }
+    startBuf++;
+  }
+  return false;
+}
+
+static void scanToNextArgument(const char *&argRef) {
+  int angle = 0;
+  while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
+    if (*argRef == '<')
+      angle++;
+    else if (*argRef == '>')
+      angle--;
+    argRef++;
+  }
+  assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
+}
+
+bool RewriteObjC::needToScanForQualifiers(QualType T) {
+  if (T->isObjCQualifiedIdType())
+    return true;
+  if (const PointerType *PT = T->getAs<PointerType>()) {
+    if (PT->getPointeeType()->isObjCQualifiedIdType())
+      return true;
+  }
+  if (T->isObjCObjectPointerType()) {
+    T = T->getPointeeType();
+    return T->isObjCQualifiedInterfaceType();
+  }
+  return false;
+}
+
+void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
+  QualType Type = E->getType();
+  if (needToScanForQualifiers(Type)) {
+    SourceLocation Loc, EndLoc;
+
+    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
+      Loc = ECE->getLParenLoc();
+      EndLoc = ECE->getRParenLoc();
+    } else {
+      Loc = E->getLocStart();
+      EndLoc = E->getLocEnd();
+    }
+    // This will defend against trying to rewrite synthesized expressions.
+    if (Loc.isInvalid() || EndLoc.isInvalid())
+      return;
+
+    const char *startBuf = SM->getCharacterData(Loc);
+    const char *endBuf = SM->getCharacterData(EndLoc);
+    const char *startRef = 0, *endRef = 0;
+    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
+      // Get the locations of the startRef, endRef.
+      SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
+      SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
+      // Comment out the protocol references.
+      InsertText(LessLoc, "/*", 2);
+      InsertText(GreaterLoc, "*/", 2);
+    }
+  }
+}
+
+void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
+  SourceLocation Loc;
+  QualType Type;
+  const FunctionProtoType *proto = 0;
+  if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
+    Loc = VD->getLocation();
+    Type = VD->getType();
+  }
+  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
+    Loc = FD->getLocation();
+    // Check for ObjC 'id' and class types that have been adorned with protocol
+    // information (id<p>, C<p>*). The protocol references need to be rewritten!
+    const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
+    assert(funcType && "missing function type");
+    proto = dyn_cast<FunctionProtoType>(funcType);
+    if (!proto)
+      return;
+    Type = proto->getResultType();
+  }
+  else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
+    Loc = FD->getLocation();
+    Type = FD->getType();
+  }
+  else
+    return;
+
+  if (needToScanForQualifiers(Type)) {
+    // Since types are unique, we need to scan the buffer.
+
+    const char *endBuf = SM->getCharacterData(Loc);
+    const char *startBuf = endBuf;
+    while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
+      startBuf--; // scan backward (from the decl location) for return type.
+    const char *startRef = 0, *endRef = 0;
+    if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
+      // Get the locations of the startRef, endRef.
+      SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
+      SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
+      // Comment out the protocol references.
+      InsertText(LessLoc, "/*", 2);
+      InsertText(GreaterLoc, "*/", 2);
+    }
+  }
+  if (!proto)
+      return; // most likely, was a variable
+  // Now check arguments.
+  const char *startBuf = SM->getCharacterData(Loc);
+  const char *startFuncBuf = startBuf;
+  for (unsigned i = 0; i < proto->getNumArgs(); i++) {
+    if (needToScanForQualifiers(proto->getArgType(i))) {
+      // Since types are unique, we need to scan the buffer.
+
+      const char *endBuf = startBuf;
+      // scan forward (from the decl location) for argument types.
+      scanToNextArgument(endBuf);
+      const char *startRef = 0, *endRef = 0;
+      if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
+        // Get the locations of the startRef, endRef.
+        SourceLocation LessLoc =
+          Loc.getFileLocWithOffset(startRef-startFuncBuf);
+        SourceLocation GreaterLoc =
+          Loc.getFileLocWithOffset(endRef-startFuncBuf+1);
+        // Comment out the protocol references.
+        InsertText(LessLoc, "/*", 2);
+        InsertText(GreaterLoc, "*/", 2);
+      }
+      startBuf = ++endBuf;
+    }
+    else {
+      // If the function name is derived from a macro expansion, then the
+      // argument buffer will not follow the name. Need to speak with Chris.
+      while (*startBuf && *startBuf != ')' && *startBuf != ',')
+        startBuf++; // scan forward (from the decl location) for argument types.
+      startBuf++;
+    }
+  }
+}
+
+// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
+void RewriteObjC::SynthSelGetUidFunctionDecl() {
+  IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
+  QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(),
+                                                   &ArgTys[0], ArgTys.size(),
+                                                   false /*isVariadic*/, 0);
+  SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                           SourceLocation(),
+                                           SelGetUidIdent, getFuncType, 0,
+                                           FunctionDecl::Extern, false);
+}
+
+void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
+  // declared in <objc/objc.h>
+  if (FD->getIdentifier() &&
+      strcmp(FD->getNameAsCString(), "sel_registerName") == 0) {
+    SelGetUidFunctionDecl = FD;
+    return;
+  }
+  RewriteObjCQualifiedInterfaceTypes(FD);
+}
+
+void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
+  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
+  const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
+  const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
+  if (!proto)
+    return;
+  QualType Type = proto->getResultType();
+  std::string FdStr = Type.getAsString();
+  FdStr += " ";
+  FdStr += FD->getNameAsCString();
+  FdStr +=  "(";
+  unsigned numArgs = proto->getNumArgs();
+  for (unsigned i = 0; i < numArgs; i++) {
+    QualType ArgType = proto->getArgType(i);
+    FdStr += ArgType.getAsString();
+    
+    if (i+1 < numArgs)
+      FdStr += ", ";
+  }
+  FdStr +=  ");\n";
+  InsertText(FunLocStart, FdStr.c_str(), FdStr.size());
+  CurFunctionDeclToDeclareForBlock = 0;
+}
+
+// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
+void RewriteObjC::SynthSuperContructorFunctionDecl() {
+  if (SuperContructorFunctionDecl)
+    return;
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  QualType argT = Context->getObjCIdType();
+  assert(!argT.isNull() && "Can't find 'id' type");
+  ArgTys.push_back(argT);
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  false, 0);
+  SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                         SourceLocation(),
+                                         msgSendIdent, msgSendType, 0,
+                                         FunctionDecl::Extern, false);
+}
+
+// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
+void RewriteObjC::SynthMsgSendFunctionDecl() {
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  QualType argT = Context->getObjCIdType();
+  assert(!argT.isNull() && "Can't find 'id' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjCSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/, 0);
+  MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                         SourceLocation(),
+                                         msgSendIdent, msgSendType, 0,
+                                         FunctionDecl::Extern, false);
+}
+
+// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
+void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                      SourceLocation(),
+                                      &Context->Idents.get("objc_super"));
+  QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+  assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjCSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/, 0);
+  MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                              SourceLocation(),
+                                              msgSendIdent, msgSendType, 0,
+                                              FunctionDecl::Extern, false);
+}
+
+// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
+void RewriteObjC::SynthMsgSendStretFunctionDecl() {
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  QualType argT = Context->getObjCIdType();
+  assert(!argT.isNull() && "Can't find 'id' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjCSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/, 0);
+  MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                         SourceLocation(),
+                                         msgSendIdent, msgSendType, 0,
+                                         FunctionDecl::Extern, false);
+}
+
+// SynthMsgSendSuperStretFunctionDecl -
+// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
+void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
+  IdentifierInfo *msgSendIdent =
+    &Context->Idents.get("objc_msgSendSuper_stret");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                      SourceLocation(),
+                                      &Context->Idents.get("objc_super"));
+  QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+  assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjCSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/, 0);
+  MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                                       SourceLocation(),
+                                              msgSendIdent, msgSendType, 0,
+                                              FunctionDecl::Extern, false);
+}
+
+// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
+void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  QualType argT = Context->getObjCIdType();
+  assert(!argT.isNull() && "Can't find 'id' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjCSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->DoubleTy,
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/, 0);
+  MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                              SourceLocation(),
+                                              msgSendIdent, msgSendType, 0,
+                                              FunctionDecl::Extern, false);
+}
+
+// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
+void RewriteObjC::SynthGetClassFunctionDecl() {
+  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
+  QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
+                                                   &ArgTys[0], ArgTys.size(),
+                                                   false /*isVariadic*/, 0);
+  GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                          SourceLocation(),
+                                          getClassIdent, getClassType, 0,
+                                          FunctionDecl::Extern, false);
+}
+
+// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
+void RewriteObjC::SynthGetMetaClassFunctionDecl() {
+  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
+  QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
+                                                   &ArgTys[0], ArgTys.size(),
+                                                   false /*isVariadic*/, 0);
+  GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+                                              SourceLocation(),
+                                              getClassIdent, getClassType, 0,
+                                              FunctionDecl::Extern, false);
+}
+
+Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
+  QualType strType = getConstantStringStructType();
+
+  std::string S = "__NSConstantStringImpl_";
+
+  std::string tmpName = InFileName;
+  unsigned i;
+  for (i=0; i < tmpName.length(); i++) {
+    char c = tmpName.at(i);
+    // replace any non alphanumeric characters with '_'.
+    if (!isalpha(c) && (c < '0' || c > '9'))
+      tmpName[i] = '_';
+  }
+  S += tmpName;
+  S += "_";
+  S += utostr(NumObjCStringLiterals++);
+
+  Preamble += "static __NSConstantStringImpl " + S;
+  Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
+  Preamble += "0x000007c8,"; // utf8_str
+  // The pretty printer for StringLiteral handles escape characters properly.
+  std::string prettyBufS;
+  llvm::raw_string_ostream prettyBuf(prettyBufS);
+  Exp->getString()->printPretty(prettyBuf, *Context, 0,
+                                PrintingPolicy(LangOpts));
+  Preamble += prettyBuf.str();
+  Preamble += ",";
+  Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
+
+  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+                                    &Context->Idents.get(S.c_str()), strType, 0,
+                                    VarDecl::Static);
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation());
+  Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
+                                 Context->getPointerType(DRE->getType()),
+                                 SourceLocation());
+  // cast to NSConstantString *
+  CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
+                                            CastExpr::CK_Unknown, Unop);
+  ReplaceStmt(Exp, cast);
+  // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+  return cast;
+}
+
+ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) {
+  // check if we are sending a message to 'super'
+  if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
+
+  if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
+      const ObjCObjectPointerType *OPT =
+        Super->getType()->getAs<ObjCObjectPointerType>();
+      assert(OPT);
+      const ObjCInterfaceType *IT = OPT->getInterfaceType();
+      return IT->getDecl();
+    }
+  return 0;
+}
+
+// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
+QualType RewriteObjC::getSuperStructType() {
+  if (!SuperStructDecl) {
+    SuperStructDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                         SourceLocation(),
+                                         &Context->Idents.get("objc_super"));
+    QualType FieldTypes[2];
+
+    // struct objc_object *receiver;
+    FieldTypes[0] = Context->getObjCIdType();
+    // struct objc_class *super;
+    FieldTypes[1] = Context->getObjCClassType();
+
+    // Create fields
+    for (unsigned i = 0; i < 2; ++i) {
+      SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
+                                                 SourceLocation(), 0,
+                                                 FieldTypes[i], 0,
+                                                 /*BitWidth=*/0,
+                                                 /*Mutable=*/false));
+    }
+
+    SuperStructDecl->completeDefinition(*Context);
+  }
+  return Context->getTagDeclType(SuperStructDecl);
+}
+
+QualType RewriteObjC::getConstantStringStructType() {
+  if (!ConstantStringDecl) {
+    ConstantStringDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                            SourceLocation(),
+                         &Context->Idents.get("__NSConstantStringImpl"));
+    QualType FieldTypes[4];
+
+    // struct objc_object *receiver;
+    FieldTypes[0] = Context->getObjCIdType();
+    // int flags;
+    FieldTypes[1] = Context->IntTy;
+    // char *str;
+    FieldTypes[2] = Context->getPointerType(Context->CharTy);
+    // long length;
+    FieldTypes[3] = Context->LongTy;
+
+    // Create fields
+    for (unsigned i = 0; i < 4; ++i) {
+      ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
+                                                    ConstantStringDecl,
+                                                    SourceLocation(), 0,
+                                                    FieldTypes[i], 0,
+                                                    /*BitWidth=*/0,
+                                                    /*Mutable=*/true));
+    }
+
+    ConstantStringDecl->completeDefinition(*Context);
+  }
+  return Context->getTagDeclType(ConstantStringDecl);
+}
+
+Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
+  if (!SelGetUidFunctionDecl)
+    SynthSelGetUidFunctionDecl();
+  if (!MsgSendFunctionDecl)
+    SynthMsgSendFunctionDecl();
+  if (!MsgSendSuperFunctionDecl)
+    SynthMsgSendSuperFunctionDecl();
+  if (!MsgSendStretFunctionDecl)
+    SynthMsgSendStretFunctionDecl();
+  if (!MsgSendSuperStretFunctionDecl)
+    SynthMsgSendSuperStretFunctionDecl();
+  if (!MsgSendFpretFunctionDecl)
+    SynthMsgSendFpretFunctionDecl();
+  if (!GetClassFunctionDecl)
+    SynthGetClassFunctionDecl();
+  if (!GetMetaClassFunctionDecl)
+    SynthGetMetaClassFunctionDecl();
+
+  // default to objc_msgSend().
+  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
+  // May need to use objc_msgSend_stret() as well.
+  FunctionDecl *MsgSendStretFlavor = 0;
+  if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
+    QualType resultType = mDecl->getResultType();
+    if (resultType->isStructureType() || resultType->isUnionType())
+      MsgSendStretFlavor = MsgSendStretFunctionDecl;
+    else if (resultType->isRealFloatingType())
+      MsgSendFlavor = MsgSendFpretFunctionDecl;
+  }
+
+  // Synthesize a call to objc_msgSend().
+  llvm::SmallVector<Expr*, 8> MsgExprs;
+  IdentifierInfo *clsName = Exp->getClassName();
+
+  // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
+  if (clsName) { // class message.
+    // FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle
+    // the 'super' idiom within a class method.
+    if (clsName->getName() == "super") {
+      MsgSendFlavor = MsgSendSuperFunctionDecl;
+      if (MsgSendStretFlavor)
+        MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
+      assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+
+      ObjCInterfaceDecl *SuperDecl =
+        CurMethodDef->getClassInterface()->getSuperClass();
+
+      llvm::SmallVector<Expr*, 4> InitExprs;
+
+      // set the receiver to self, the first argument to all methods.
+      InitExprs.push_back(
+        NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+                                 CastExpr::CK_Unknown,
+                     new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+                                     Context->getObjCIdType(),
+                                     SourceLocation()))
+                          ); // set the 'receiver'.
+
+      llvm::SmallVector<Expr*, 8> ClsExprs;
+      QualType argType = Context->getPointerType(Context->CharTy);
+      ClsExprs.push_back(StringLiteral::Create(*Context,
+                                     SuperDecl->getIdentifier()->getNameStart(),
+                                     SuperDecl->getIdentifier()->getLength(),
+                                     false, argType, SourceLocation()));
+      CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
+                                                   &ClsExprs[0],
+                                                   ClsExprs.size());
+      // To turn off a warning, type-cast to 'id'
+      InitExprs.push_back( // set 'super class', using objc_getClass().
+                          NoTypeInfoCStyleCastExpr(Context,
+                                                   Context->getObjCIdType(),
+                                                   CastExpr::CK_Unknown, Cls));
+      // struct objc_super
+      QualType superType = getSuperStructType();
+      Expr *SuperRep;
+
+      if (LangOpts.Microsoft) {
+        SynthSuperContructorFunctionDecl();
+        // Simulate a contructor call...
+        DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
+                                           superType, SourceLocation());
+        SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
+                                          InitExprs.size(),
+                                          superType, SourceLocation());
+        // The code for super is a little tricky to prevent collision with
+        // the structure definition in the header. The rewriter has it's own
+        // internal definition (__rw_objc_super) that is uses. This is why
+        // we need the cast below. For example:
+        // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
+        //
+        SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+                                 Context->getPointerType(SuperRep->getType()),
+                                 SourceLocation());
+        SuperRep = NoTypeInfoCStyleCastExpr(Context,
+                                            Context->getPointerType(superType),
+                                            CastExpr::CK_Unknown, SuperRep);
+      } else {
+        // (struct objc_super) { <exprs from above> }
+        InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
+                                             &InitExprs[0], InitExprs.size(),
+                                             SourceLocation());
+        TypeSourceInfo *superTInfo
+          = Context->getTrivialTypeSourceInfo(superType);
+        SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
+                                                     superType, ILE, false);
+        // struct objc_super *
+        SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+                                 Context->getPointerType(SuperRep->getType()),
+                                 SourceLocation());
+      }
+      MsgExprs.push_back(SuperRep);
+    } else {
+      llvm::SmallVector<Expr*, 8> ClsExprs;
+      QualType argType = Context->getPointerType(Context->CharTy);
+      ClsExprs.push_back(StringLiteral::Create(*Context,
+                                               clsName->getNameStart(),
+                                               clsName->getLength(),
+                                               false, argType,
+                                               SourceLocation()));
+      CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+                                                   &ClsExprs[0],
+                                                   ClsExprs.size());
+      MsgExprs.push_back(Cls);
+    }
+  } else { // instance message.
+    Expr *recExpr = Exp->getReceiver();
+
+    if (ObjCInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
+      MsgSendFlavor = MsgSendSuperFunctionDecl;
+      if (MsgSendStretFlavor)
+        MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
+      assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+
+      llvm::SmallVector<Expr*, 4> InitExprs;
+
+      InitExprs.push_back(
+        NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+                                 CastExpr::CK_Unknown,
+                     new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+                                     Context->getObjCIdType(),
+                                     SourceLocation()))
+                          ); // set the 'receiver'.
+
+      llvm::SmallVector<Expr*, 8> ClsExprs;
+      QualType argType = Context->getPointerType(Context->CharTy);
+      ClsExprs.push_back(StringLiteral::Create(*Context,
+                                     SuperDecl->getIdentifier()->getNameStart(),
+                                     SuperDecl->getIdentifier()->getLength(),
+                                     false, argType, SourceLocation()));
+      CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+                                                   &ClsExprs[0],
+                                                   ClsExprs.size());
+      // To turn off a warning, type-cast to 'id'
+      InitExprs.push_back(
+        // set 'super class', using objc_getClass().
+        NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+                                 CastExpr::CK_Unknown, Cls));
+      // struct objc_super
+      QualType superType = getSuperStructType();
+      Expr *SuperRep;
+
+      if (LangOpts.Microsoft) {
+        SynthSuperContructorFunctionDecl();
+        // Simulate a contructor call...
+        DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
+                                           superType, SourceLocation());
+        SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
+                                          InitExprs.size(),
+                                          superType, SourceLocation());
+        // The code for super is a little tricky to prevent collision with
+        // the structure definition in the header. The rewriter has it's own
+        // internal definition (__rw_objc_super) that is uses. This is why
+        // we need the cast below. For example:
+        // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
+        //
+        SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+                                 Context->getPointerType(SuperRep->getType()),
+                                 SourceLocation());
+        SuperRep = NoTypeInfoCStyleCastExpr(Context,
+                                 Context->getPointerType(superType),
+                                 CastExpr::CK_Unknown, SuperRep);
+      } else {
+        // (struct objc_super) { <exprs from above> }
+        InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
+                                             &InitExprs[0], InitExprs.size(),
+                                             SourceLocation());
+        TypeSourceInfo *superTInfo
+          = Context->getTrivialTypeSourceInfo(superType);
+        SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
+                                                     superType, ILE, false);
+      }
+      MsgExprs.push_back(SuperRep);
+    } else {
+      // Remove all type-casts because it may contain objc-style types; e.g.
+      // Foo<Proto> *.
+      while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
+        recExpr = CE->getSubExpr();
+      recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+                                         CastExpr::CK_Unknown, recExpr);
+      MsgExprs.push_back(recExpr);
+    }
+  }
+  // Create a call to sel_registerName("selName"), it will be the 2nd argument.
+  llvm::SmallVector<Expr*, 8> SelExprs;
+  QualType argType = Context->getPointerType(Context->CharTy);
+  SelExprs.push_back(StringLiteral::Create(*Context,
+                                       Exp->getSelector().getAsString().c_str(),
+                                       Exp->getSelector().getAsString().size(),
+                                       false, argType, SourceLocation()));
+  CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
+                                                 &SelExprs[0], SelExprs.size());
+  MsgExprs.push_back(SelExp);
+
+  // Now push any user supplied arguments.
+  for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
+    Expr *userExpr = Exp->getArg(i);
+    // Make all implicit casts explicit...ICE comes in handy:-)
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
+      // Reuse the ICE type, it is exactly what the doctor ordered.
+      QualType type = ICE->getType()->isObjCQualifiedIdType()
+                                ? Context->getObjCIdType()
+                                : ICE->getType();
+      userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown,
+                                          userExpr);
+    }
+    // Make id<P...> cast into an 'id' cast.
+    else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
+      if (CE->getType()->isObjCQualifiedIdType()) {
+        while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
+          userExpr = CE->getSubExpr();
+        userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+                                            CastExpr::CK_Unknown, userExpr);
+      }
+    }
+    MsgExprs.push_back(userExpr);
+    // We've transferred the ownership to MsgExprs. For now, we *don't* null
+    // out the argument in the original expression (since we aren't deleting
+    // the ObjCMessageExpr). See RewritePropertySetter() usage for more info.
+    //Exp->setArg(i, 0);
+  }
+  // Generate the funky cast.
+  CastExpr *cast;
+  llvm::SmallVector<QualType, 8> ArgTypes;
+  QualType returnType;
+
+  // Push 'id' and 'SEL', the 2 implicit arguments.
+  if (MsgSendFlavor == MsgSendSuperFunctionDecl)
+    ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
+  else
+    ArgTypes.push_back(Context->getObjCIdType());
+  ArgTypes.push_back(Context->getObjCSelType());
+  if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
+    // Push any user argument types.
+    for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+         E = OMD->param_end(); PI != E; ++PI) {
+      QualType t = (*PI)->getType()->isObjCQualifiedIdType()
+                     ? Context->getObjCIdType()
+                     : (*PI)->getType();
+      // Make sure we convert "t (^)(...)" to "t (*)(...)".
+      if (isTopLevelBlockPointerType(t)) {
+        const BlockPointerType *BPT = t->getAs<BlockPointerType>();
+        t = Context->getPointerType(BPT->getPointeeType());
+      }
+      ArgTypes.push_back(t);
+    }
+    returnType = OMD->getResultType()->isObjCQualifiedIdType()
+                   ? Context->getObjCIdType() : OMD->getResultType();
+  } else {
+    returnType = Context->getObjCIdType();
+  }
+  // Get the type, we will need to reference it in a couple spots.
+  QualType msgSendType = MsgSendFlavor->getType();
+
+  // Create a reference to the objc_msgSend() declaration.
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType,
+                                     SourceLocation());
+
+  // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
+  // If we don't do this cast, we get the following bizarre warning/note:
+  // xx.m:13: warning: function called through a non-compatible type
+  // xx.m:13: note: if this code is reached, the program will abort
+  cast = NoTypeInfoCStyleCastExpr(Context,
+                                  Context->getPointerType(Context->VoidTy),
+                                  CastExpr::CK_Unknown, DRE);
+
+  // Now do the "normal" pointer to function cast.
+  QualType castType = Context->getFunctionType(returnType,
+    &ArgTypes[0], ArgTypes.size(),
+    // If we don't have a method decl, force a variadic cast.
+    Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0);
+  castType = Context->getPointerType(castType);
+  cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
+                                  cast);
+
+  // Don't forget the parens to enforce the proper binding.
+  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
+
+  const FunctionType *FT = msgSendType->getAs<FunctionType>();
+  CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
+                                        MsgExprs.size(),
+                                        FT->getResultType(), SourceLocation());
+  Stmt *ReplacingStmt = CE;
+  if (MsgSendStretFlavor) {
+    // We have the method which returns a struct/union. Must also generate
+    // call to objc_msgSend_stret and hang both varieties on a conditional
+    // expression which dictate which one to envoke depending on size of
+    // method's return type.
+
+    // Create a reference to the objc_msgSend_stret() declaration.
+    DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType,
+                                         SourceLocation());
+    // Need to cast objc_msgSend_stret to "void *" (see above comment).
+    cast = NoTypeInfoCStyleCastExpr(Context,
+                                    Context->getPointerType(Context->VoidTy),
+                                    CastExpr::CK_Unknown, STDRE);
+    // Now do the "normal" pointer to function cast.
+    castType = Context->getFunctionType(returnType,
+      &ArgTypes[0], ArgTypes.size(),
+      Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0);
+    castType = Context->getPointerType(castType);
+    cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
+                                    cast);
+
+    // Don't forget the parens to enforce the proper binding.
+    PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
+
+    FT = msgSendType->getAs<FunctionType>();
+    CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
+                                            MsgExprs.size(),
+                                            FT->getResultType(), SourceLocation());
+
+    // Build sizeof(returnType)
+    SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
+                            Context->getTrivialTypeSourceInfo(returnType),
+                                      Context->getSizeType(),
+                                      SourceLocation(), SourceLocation());
+    // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
+    // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
+    // For X86 it is more complicated and some kind of target specific routine
+    // is needed to decide what to do.
+    unsigned IntSize =
+      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+    IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8),
+                                               Context->IntTy,
+                                               SourceLocation());
+    BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit,
+                                                      BinaryOperator::LE,
+                                                      Context->IntTy,
+                                                      SourceLocation());
+    // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
+    ConditionalOperator *CondExpr =
+      new (Context) ConditionalOperator(lessThanExpr,
+                                        SourceLocation(), CE,
+                                        SourceLocation(), STCE, returnType);
+    ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
+  }
+  // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+  return ReplacingStmt;
+}
+
+Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
+  Stmt *ReplacingStmt = SynthMessageExpr(Exp);
+
+  // Now do the actual rewrite.
+  ReplaceStmt(Exp, ReplacingStmt);
+
+  // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+  return ReplacingStmt;
+}
+
+// typedef struct objc_object Protocol;
+QualType RewriteObjC::getProtocolType() {
+  if (!ProtocolTypeDecl) {
+    TypeSourceInfo *TInfo
+      = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
+    ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
+                                           SourceLocation(),
+                                           &Context->Idents.get("Protocol"),
+                                           TInfo);
+  }
+  return Context->getTypeDeclType(ProtocolTypeDecl);
+}
+
+/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
+/// a synthesized/forward data reference (to the protocol's metadata).
+/// The forward references (and metadata) are generated in
+/// RewriteObjC::HandleTranslationUnit().
+Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
+  std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
+  IdentifierInfo *ID = &Context->Idents.get(Name);
+  VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+                                ID, getProtocolType(), 0, VarDecl::Extern);
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation());
+  Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
+                             Context->getPointerType(DRE->getType()),
+                             SourceLocation());
+  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
+                                                CastExpr::CK_Unknown,
+                                                DerefExpr);
+  ReplaceStmt(Exp, castExpr);
+  ProtocolExprDecls.insert(Exp->getProtocol());
+  // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+  return castExpr;
+
+}
+
+bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
+                                             const char *endBuf) {
+  while (startBuf < endBuf) {
+    if (*startBuf == '#') {
+      // Skip whitespace.
+      for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
+        ;
+      if (!strncmp(startBuf, "if", strlen("if")) ||
+          !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
+          !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
+          !strncmp(startBuf, "define", strlen("define")) ||
+          !strncmp(startBuf, "undef", strlen("undef")) ||
+          !strncmp(startBuf, "else", strlen("else")) ||
+          !strncmp(startBuf, "elif", strlen("elif")) ||
+          !strncmp(startBuf, "endif", strlen("endif")) ||
+          !strncmp(startBuf, "pragma", strlen("pragma")) ||
+          !strncmp(startBuf, "include", strlen("include")) ||
+          !strncmp(startBuf, "import", strlen("import")) ||
+          !strncmp(startBuf, "include_next", strlen("include_next")))
+        return true;
+    }
+    startBuf++;
+  }
+  return false;
+}
+
+/// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to
+/// an objective-c class with ivars.
+void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
+                                               std::string &Result) {
+  assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
+  assert(CDecl->getNameAsCString() &&
+         "Name missing in SynthesizeObjCInternalStruct");
+  // Do not synthesize more than once.
+  if (ObjCSynthesizedStructs.count(CDecl))
+    return;
+  ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
+  int NumIvars = CDecl->ivar_size();
+  SourceLocation LocStart = CDecl->getLocStart();
+  SourceLocation LocEnd = CDecl->getLocEnd();
+
+  const char *startBuf = SM->getCharacterData(LocStart);
+  const char *endBuf = SM->getCharacterData(LocEnd);
+
+  // If no ivars and no root or if its root, directly or indirectly,
+  // have no ivars (thus not synthesized) then no need to synthesize this class.
+  if ((CDecl->isForwardDecl() || NumIvars == 0) &&
+      (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
+    endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
+    ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size());
+    return;
+  }
+
+  // FIXME: This has potential of causing problem. If
+  // SynthesizeObjCInternalStruct is ever called recursively.
+  Result += "\nstruct ";
+  Result += CDecl->getNameAsString();
+  if (LangOpts.Microsoft)
+    Result += "_IMPL";
+
+  if (NumIvars > 0) {
+    const char *cursor = strchr(startBuf, '{');
+    assert((cursor && endBuf)
+           && "SynthesizeObjCInternalStruct - malformed @interface");
+    // If the buffer contains preprocessor directives, we do more fine-grained
+    // rewrites. This is intended to fix code that looks like (which occurs in
+    // NSURL.h, for example):
+    //
+    // #ifdef XYZ
+    // @interface Foo : NSObject
+    // #else
+    // @interface FooBar : NSObject
+    // #endif
+    // {
+    //    int i;
+    // }
+    // @end
+    //
+    // This clause is segregated to avoid breaking the common case.
+    if (BufferContainsPPDirectives(startBuf, cursor)) {
+      SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
+                                  CDecl->getClassLoc();
+      const char *endHeader = SM->getCharacterData(L);
+      endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
+
+      if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+        // advance to the end of the referenced protocols.
+        while (endHeader < cursor && *endHeader != '>') endHeader++;
+        endHeader++;
+      }
+      // rewrite the original header
+      ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size());
+    } else {
+      // rewrite the original header *without* disturbing the '{'
+      ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size());
+    }
+    if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
+      Result = "\n    struct ";
+      Result += RCDecl->getNameAsString();
+      Result += "_IMPL ";
+      Result += RCDecl->getNameAsString();
+      Result += "_IVARS;\n";
+
+      // insert the super class structure definition.
+      SourceLocation OnePastCurly =
+        LocStart.getFileLocWithOffset(cursor-startBuf+1);
+      InsertText(OnePastCurly, Result.c_str(), Result.size());
+    }
+    cursor++; // past '{'
+
+    // Now comment out any visibility specifiers.
+    while (cursor < endBuf) {
+      if (*cursor == '@') {
+        SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+        // Skip whitespace.
+        for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
+          /*scan*/;
+
+        // FIXME: presence of @public, etc. inside comment results in
+        // this transformation as well, which is still correct c-code.
+        if (!strncmp(cursor, "public", strlen("public")) ||
+            !strncmp(cursor, "private", strlen("private")) ||
+            !strncmp(cursor, "package", strlen("package")) ||
+            !strncmp(cursor, "protected", strlen("protected")))
+          InsertText(atLoc, "// ", 3);
+      }
+      // FIXME: If there are cases where '<' is used in ivar declaration part
+      // of user code, then scan the ivar list and use needToScanForQualifiers
+      // for type checking.
+      else if (*cursor == '<') {
+        SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+        InsertText(atLoc, "/* ", 3);
+        cursor = strchr(cursor, '>');
+        cursor++;
+        atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+        InsertText(atLoc, " */", 3);
+      } else if (*cursor == '^') { // rewrite block specifier.
+        SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+        ReplaceText(caretLoc, 1, "*", 1);
+      }
+      cursor++;
+    }
+    // Don't forget to add a ';'!!
+    InsertText(LocEnd.getFileLocWithOffset(1), ";", 1);
+  } else { // we don't have any instance variables - insert super struct.
+    endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
+    Result += " {\n    struct ";
+    Result += RCDecl->getNameAsString();
+    Result += "_IMPL ";
+    Result += RCDecl->getNameAsString();
+    Result += "_IVARS;\n};\n";
+    ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size());
+  }
+  // Mark this struct as having been generated.
+  if (!ObjCSynthesizedStructs.insert(CDecl))
+    assert(false && "struct already synthesize- SynthesizeObjCInternalStruct");
+}
+
+// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
+/// class methods.
+template<typename MethodIterator>
+void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+                                             MethodIterator MethodEnd,
+                                             bool IsInstanceMethod,
+                                             const char *prefix,
+                                             const char *ClassName,
+                                             std::string &Result) {
+  if (MethodBegin == MethodEnd) return;
+
+  if (!objc_impl_method) {
+    /* struct _objc_method {
+       SEL _cmd;
+       char *method_types;
+       void *_imp;
+       }
+     */
+    Result += "\nstruct _objc_method {\n";
+    Result += "\tSEL _cmd;\n";
+    Result += "\tchar *method_types;\n";
+    Result += "\tvoid *_imp;\n";
+    Result += "};\n";
+
+    objc_impl_method = true;
+  }
+
+  // Build _objc_method_list for class's methods if needed
+
+  /* struct  {
+   struct _objc_method_list *next_method;
+   int method_count;
+   struct _objc_method method_list[];
+   }
+   */
+  unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
+  Result += "\nstatic struct {\n";
+  Result += "\tstruct _objc_method_list *next_method;\n";
+  Result += "\tint method_count;\n";
+  Result += "\tstruct _objc_method method_list[";
+  Result += utostr(NumMethods);
+  Result += "];\n} _OBJC_";
+  Result += prefix;
+  Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
+  Result += "_METHODS_";
+  Result += ClassName;
+  Result += " __attribute__ ((used, section (\"__OBJC, __";
+  Result += IsInstanceMethod ? "inst" : "cls";
+  Result += "_meth\")))= ";
+  Result += "{\n\t0, " + utostr(NumMethods) + "\n";
+
+  Result += "\t,{{(SEL)\"";
+  Result += (*MethodBegin)->getSelector().getAsString().c_str();
+  std::string MethodTypeString;
+  Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+  Result += "\", \"";
+  Result += MethodTypeString;
+  Result += "\", (void *)";
+  Result += MethodInternalNames[*MethodBegin];
+  Result += "}\n";
+  for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
+    Result += "\t  ,{(SEL)\"";
+    Result += (*MethodBegin)->getSelector().getAsString().c_str();
+    std::string MethodTypeString;
+    Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+    Result += "\", \"";
+    Result += MethodTypeString;
+    Result += "\", (void *)";
+    Result += MethodInternalNames[*MethodBegin];
+    Result += "}\n";
+  }
+  Result += "\t }\n};\n";
+}
+
+/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
+void RewriteObjC::
+RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix,
+                            const char *ClassName, std::string &Result) {
+  static bool objc_protocol_methods = false;
+
+  // Output struct protocol_methods holder of method selector and type.
+  if (!objc_protocol_methods && !PDecl->isForwardDecl()) {
+    /* struct protocol_methods {
+     SEL _cmd;
+     char *method_types;
+     }
+     */
+    Result += "\nstruct _protocol_methods {\n";
+    Result += "\tstruct objc_selector *_cmd;\n";
+    Result += "\tchar *method_types;\n";
+    Result += "};\n";
+
+    objc_protocol_methods = true;
+  }
+  // Do not synthesize the protocol more than once.
+  if (ObjCSynthesizedProtocols.count(PDecl))
+    return;
+
+    if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
+      unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
+                                          PDecl->instmeth_end());
+    /* struct _objc_protocol_method_list {
+     int protocol_method_count;
+     struct protocol_methods protocols[];
+     }
+     */
+    Result += "\nstatic struct {\n";
+    Result += "\tint protocol_method_count;\n";
+    Result += "\tstruct _protocol_methods protocol_methods[";
+    Result += utostr(NumMethods);
+    Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
+      "{\n\t" + utostr(NumMethods) + "\n";
+
+    // Output instance methods declared in this protocol.
+    for (ObjCProtocolDecl::instmeth_iterator
+           I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
+         I != E; ++I) {
+      if (I == PDecl->instmeth_begin())
+        Result += "\t  ,{{(struct objc_selector *)\"";
+      else
+        Result += "\t  ,{(struct objc_selector *)\"";
+      Result += (*I)->getSelector().getAsString().c_str();
+      std::string MethodTypeString;
+      Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+      Result += "\", \"";
+      Result += MethodTypeString;
+      Result += "\"}\n";
+    }
+    Result += "\t }\n};\n";
+  }
+
+  // Output class methods declared in this protocol.
+  unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
+                                      PDecl->classmeth_end());
+  if (NumMethods > 0) {
+    /* struct _objc_protocol_method_list {
+     int protocol_method_count;
+     struct protocol_methods protocols[];
+     }
+     */
+    Result += "\nstatic struct {\n";
+    Result += "\tint protocol_method_count;\n";
+    Result += "\tstruct _protocol_methods protocol_methods[";
+    Result += utostr(NumMethods);
+    Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
+           "{\n\t";
+    Result += utostr(NumMethods);
+    Result += "\n";
+
+    // Output instance methods declared in this protocol.
+    for (ObjCProtocolDecl::classmeth_iterator
+           I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+         I != E; ++I) {
+      if (I == PDecl->classmeth_begin())
+        Result += "\t  ,{{(struct objc_selector *)\"";
+      else
+        Result += "\t  ,{(struct objc_selector *)\"";
+      Result += (*I)->getSelector().getAsString().c_str();
+      std::string MethodTypeString;
+      Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+      Result += "\", \"";
+      Result += MethodTypeString;
+      Result += "\"}\n";
+    }
+    Result += "\t }\n};\n";
+  }
+
+  // Output:
+  /* struct _objc_protocol {
+   // Objective-C 1.0 extensions
+   struct _objc_protocol_extension *isa;
+   char *protocol_name;
+   struct _objc_protocol **protocol_list;
+   struct _objc_protocol_method_list *instance_methods;
+   struct _objc_protocol_method_list *class_methods;
+   };
+   */
+  static bool objc_protocol = false;
+  if (!objc_protocol) {
+    Result += "\nstruct _objc_protocol {\n";
+    Result += "\tstruct _objc_protocol_extension *isa;\n";
+    Result += "\tchar *protocol_name;\n";
+    Result += "\tstruct _objc_protocol **protocol_list;\n";
+    Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
+    Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
+    Result += "};\n";
+
+    objc_protocol = true;
+  }
+
+  Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
+  Result += PDecl->getNameAsString();
+  Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
+    "{\n\t0, \"";
+  Result += PDecl->getNameAsString();
+  Result += "\", 0, ";
+  if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
+    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += ", ";
+  }
+  else
+    Result += "0, ";
+  if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
+    Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
+    Result += PDecl->getNameAsString();
+    Result += "\n";
+  }
+  else
+    Result += "0\n";
+  Result += "};\n";
+
+  // Mark this protocol as having been generated.
+  if (!ObjCSynthesizedProtocols.insert(PDecl))
+    assert(false && "protocol already synthesized");
+
+}
+
+void RewriteObjC::
+RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols,
+                                const char *prefix, const char *ClassName,
+                                std::string &Result) {
+  if (Protocols.empty()) return;
+
+  for (unsigned i = 0; i != Protocols.size(); i++)
+    RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
+
+  // Output the top lovel protocol meta-data for the class.
+  /* struct _objc_protocol_list {
+   struct _objc_protocol_list *next;
+   int    protocol_count;
+   struct _objc_protocol *class_protocols[];
+   }
+   */
+  Result += "\nstatic struct {\n";
+  Result += "\tstruct _objc_protocol_list *next;\n";
+  Result += "\tint    protocol_count;\n";
+  Result += "\tstruct _objc_protocol *class_protocols[";
+  Result += utostr(Protocols.size());
+  Result += "];\n} _OBJC_";
+  Result += prefix;
+  Result += "_PROTOCOLS_";
+  Result += ClassName;
+  Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
+    "{\n\t0, ";
+  Result += utostr(Protocols.size());
+  Result += "\n";
+
+  Result += "\t,{&_OBJC_PROTOCOL_";
+  Result += Protocols[0]->getNameAsString();
+  Result += " \n";
+
+  for (unsigned i = 1; i != Protocols.size(); i++) {
+    Result += "\t ,&_OBJC_PROTOCOL_";
+    Result += Protocols[i]->getNameAsString();
+    Result += "\n";
+  }
+  Result += "\t }\n};\n";
+}
+
+
+/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
+/// implementation.
+void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
+                                              std::string &Result) {
+  ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
+  // Find category declaration for this implementation.
+  ObjCCategoryDecl *CDecl;
+  for (CDecl = ClassDecl->getCategoryList(); CDecl;
+       CDecl = CDecl->getNextClassCategory())
+    if (CDecl->getIdentifier() == IDecl->getIdentifier())
+      break;
+
+  std::string FullCategoryName = ClassDecl->getNameAsString();
+  FullCategoryName += '_';
+  FullCategoryName += IDecl->getNameAsString();
+
+  // Build _objc_method_list for class's instance methods if needed
+  llvm::SmallVector<ObjCMethodDecl *, 32>
+    InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+
+  // If any of our property implementations have associated getters or
+  // setters, produce metadata for them as well.
+  for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
+         PropEnd = IDecl->propimpl_end();
+       Prop != PropEnd; ++Prop) {
+    if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+      continue;
+    if (!(*Prop)->getPropertyIvarDecl())
+      continue;
+    ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
+    if (!PD)
+      continue;
+    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+      InstanceMethods.push_back(Getter);
+    if (PD->isReadOnly())
+      continue;
+    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+      InstanceMethods.push_back(Setter);
+  }
+  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
+                             true, "CATEGORY_", FullCategoryName.c_str(),
+                             Result);
+
+  // Build _objc_method_list for class's class methods if needed
+  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
+                             false, "CATEGORY_", FullCategoryName.c_str(),
+                             Result);
+
+  // Protocols referenced in class declaration?
+  // Null CDecl is case of a category implementation with no category interface
+  if (CDecl)
+    RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
+                                    FullCategoryName.c_str(), Result);
+  /* struct _objc_category {
+   char *category_name;
+   char *class_name;
+   struct _objc_method_list *instance_methods;
+   struct _objc_method_list *class_methods;
+   struct _objc_protocol_list *protocols;
+   // Objective-C 1.0 extensions
+   uint32_t size;     // sizeof (struct _objc_category)
+   struct _objc_property_list *instance_properties;  // category's own
+                                                     // @property decl.
+   };
+   */
+
+  static bool objc_category = false;
+  if (!objc_category) {
+    Result += "\nstruct _objc_category {\n";
+    Result += "\tchar *category_name;\n";
+    Result += "\tchar *class_name;\n";
+    Result += "\tstruct _objc_method_list *instance_methods;\n";
+    Result += "\tstruct _objc_method_list *class_methods;\n";
+    Result += "\tstruct _objc_protocol_list *protocols;\n";
+    Result += "\tunsigned int size;\n";
+    Result += "\tstruct _objc_property_list *instance_properties;\n";
+    Result += "};\n";
+    objc_category = true;
+  }
+  Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
+  Result += FullCategoryName;
+  Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
+  Result += IDecl->getNameAsString();
+  Result += "\"\n\t, \"";
+  Result += ClassDecl->getNameAsString();
+  Result += "\"\n";
+
+  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
+    Result += "\t, (struct _objc_method_list *)"
+           "&_OBJC_CATEGORY_INSTANCE_METHODS_";
+    Result += FullCategoryName;
+    Result += "\n";
+  }
+  else
+    Result += "\t, 0\n";
+  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
+    Result += "\t, (struct _objc_method_list *)"
+           "&_OBJC_CATEGORY_CLASS_METHODS_";
+    Result += FullCategoryName;
+    Result += "\n";
+  }
+  else
+    Result += "\t, 0\n";
+
+  if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
+    Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
+    Result += FullCategoryName;
+    Result += "\n";
+  }
+  else
+    Result += "\t, 0\n";
+  Result += "\t, sizeof(struct _objc_category), 0\n};\n";
+}
+
+/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
+/// ivar offset.
+void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl,
+                                                  ObjCIvarDecl *ivar,
+                                                  std::string &Result) {
+  if (ivar->isBitField()) {
+    // FIXME: The hack below doesn't work for bitfields. For now, we simply
+    // place all bitfields at offset 0.
+    Result += "0";
+  } else {
+    Result += "__OFFSETOFIVAR__(struct ";
+    Result += IDecl->getNameAsString();
+    if (LangOpts.Microsoft)
+      Result += "_IMPL";
+    Result += ", ";
+    Result += ivar->getNameAsString();
+    Result += ")";
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Meta Data Emission
+//===----------------------------------------------------------------------===//
+
+void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+                                           std::string &Result) {
+  ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
+
+  // Explictly declared @interface's are already synthesized.
+  if (CDecl->isImplicitInterfaceDecl()) {
+    // FIXME: Implementation of a class with no @interface (legacy) doese not
+    // produce correct synthesis as yet.
+    SynthesizeObjCInternalStruct(CDecl, Result);
+  }
+
+  // Build _objc_ivar_list metadata for classes ivars if needed
+  unsigned NumIvars = !IDecl->ivar_empty()
+                      ? IDecl->ivar_size()
+                      : (CDecl ? CDecl->ivar_size() : 0);
+  if (NumIvars > 0) {
+    static bool objc_ivar = false;
+    if (!objc_ivar) {
+      /* struct _objc_ivar {
+          char *ivar_name;
+          char *ivar_type;
+          int ivar_offset;
+        };
+       */
+      Result += "\nstruct _objc_ivar {\n";
+      Result += "\tchar *ivar_name;\n";
+      Result += "\tchar *ivar_type;\n";
+      Result += "\tint ivar_offset;\n";
+      Result += "};\n";
+
+      objc_ivar = true;
+    }
+
+    /* struct {
+       int ivar_count;
+       struct _objc_ivar ivar_list[nIvars];
+       };
+     */
+    Result += "\nstatic struct {\n";
+    Result += "\tint ivar_count;\n";
+    Result += "\tstruct _objc_ivar ivar_list[";
+    Result += utostr(NumIvars);
+    Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
+    Result += IDecl->getNameAsString();
+    Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
+      "{\n\t";
+    Result += utostr(NumIvars);
+    Result += "\n";
+
+    ObjCInterfaceDecl::ivar_iterator IVI, IVE;
+    llvm::SmallVector<ObjCIvarDecl *, 8> IVars;
+    if (!IDecl->ivar_empty()) {
+      for (ObjCImplementationDecl::ivar_iterator
+             IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end();
+           IV != IVEnd; ++IV)
+        IVars.push_back(*IV);
+      IVI = IVars.begin();
+      IVE = IVars.end();
+    } else {
+      IVI = CDecl->ivar_begin();
+      IVE = CDecl->ivar_end();
+    }
+    Result += "\t,{{\"";
+    Result += (*IVI)->getNameAsString();
+    Result += "\", \"";
+    std::string TmpString, StrEncoding;
+    Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
+    QuoteDoublequotes(TmpString, StrEncoding);
+    Result += StrEncoding;
+    Result += "\", ";
+    SynthesizeIvarOffsetComputation(IDecl, *IVI, Result);
+    Result += "}\n";
+    for (++IVI; IVI != IVE; ++IVI) {
+      Result += "\t  ,{\"";
+      Result += (*IVI)->getNameAsString();
+      Result += "\", \"";
+      std::string TmpString, StrEncoding;
+      Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
+      QuoteDoublequotes(TmpString, StrEncoding);
+      Result += StrEncoding;
+      Result += "\", ";
+      SynthesizeIvarOffsetComputation(IDecl, (*IVI), Result);
+      Result += "}\n";
+    }
+
+    Result += "\t }\n};\n";
+  }
+
+  // Build _objc_method_list for class's instance methods if needed
+  llvm::SmallVector<ObjCMethodDecl *, 32>
+    InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+
+  // If any of our property implementations have associated getters or
+  // setters, produce metadata for them as well.
+  for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
+         PropEnd = IDecl->propimpl_end();
+       Prop != PropEnd; ++Prop) {
+    if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+      continue;
+    if (!(*Prop)->getPropertyIvarDecl())
+      continue;
+    ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
+    if (!PD)
+      continue;
+    if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+      InstanceMethods.push_back(Getter);
+    if (PD->isReadOnly())
+      continue;
+    if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+      InstanceMethods.push_back(Setter);
+  }
+  RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
+                             true, "", IDecl->getNameAsCString(), Result);
+
+  // Build _objc_method_list for class's class methods if needed
+  RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
+                             false, "", IDecl->getNameAsCString(), Result);
+
+  // Protocols referenced in class declaration?
+  RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
+                                  "CLASS", CDecl->getNameAsCString(), Result);
+
+  // Declaration of class/meta-class metadata
+  /* struct _objc_class {
+   struct _objc_class *isa; // or const char *root_class_name when metadata
+   const char *super_class_name;
+   char *name;
+   long version;
+   long info;
+   long instance_size;
+   struct _objc_ivar_list *ivars;
+   struct _objc_method_list *methods;
+   struct objc_cache *cache;
+   struct objc_protocol_list *protocols;
+   const char *ivar_layout;
+   struct _objc_class_ext  *ext;
+   };
+  */
+  static bool objc_class = false;
+  if (!objc_class) {
+    Result += "\nstruct _objc_class {\n";
+    Result += "\tstruct _objc_class *isa;\n";
+    Result += "\tconst char *super_class_name;\n";
+    Result += "\tchar *name;\n";
+    Result += "\tlong version;\n";
+    Result += "\tlong info;\n";
+    Result += "\tlong instance_size;\n";
+    Result += "\tstruct _objc_ivar_list *ivars;\n";
+    Result += "\tstruct _objc_method_list *methods;\n";
+    Result += "\tstruct objc_cache *cache;\n";
+    Result += "\tstruct _objc_protocol_list *protocols;\n";
+    Result += "\tconst char *ivar_layout;\n";
+    Result += "\tstruct _objc_class_ext  *ext;\n";
+    Result += "};\n";
+    objc_class = true;
+  }
+
+  // Meta-class metadata generation.
+  ObjCInterfaceDecl *RootClass = 0;
+  ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
+  while (SuperClass) {
+    RootClass = SuperClass;
+    SuperClass = SuperClass->getSuperClass();
+  }
+  SuperClass = CDecl->getSuperClass();
+
+  Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
+  Result += CDecl->getNameAsString();
+  Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
+  "{\n\t(struct _objc_class *)\"";
+  Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
+  Result += "\"";
+
+  if (SuperClass) {
+    Result += ", \"";
+    Result += SuperClass->getNameAsString();
+    Result += "\", \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  else {
+    Result += ", 0, \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
+  // 'info' field is initialized to CLS_META(2) for metaclass
+  Result += ", 0,2, sizeof(struct _objc_class), 0";
+  if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
+    Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
+    Result += IDecl->getNameAsString();
+    Result += "\n";
+  }
+  else
+    Result += ", 0\n";
+  if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+    Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
+    Result += CDecl->getNameAsString();
+    Result += ",0,0\n";
+  }
+  else
+    Result += "\t,0,0,0,0\n";
+  Result += "};\n";
+
+  // class metadata generation.
+  Result += "\nstatic struct _objc_class _OBJC_CLASS_";
+  Result += CDecl->getNameAsString();
+  Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
+            "{\n\t&_OBJC_METACLASS_";
+  Result += CDecl->getNameAsString();
+  if (SuperClass) {
+    Result += ", \"";
+    Result += SuperClass->getNameAsString();
+    Result += "\", \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  else {
+    Result += ", 0, \"";
+    Result += CDecl->getNameAsString();
+    Result += "\"";
+  }
+  // 'info' field is initialized to CLS_CLASS(1) for class
+  Result += ", 0,1";
+  if (!ObjCSynthesizedStructs.count(CDecl))
+    Result += ",0";
+  else {
+    // class has size. Must synthesize its size.
+    Result += ",sizeof(struct ";
+    Result += CDecl->getNameAsString();
+    if (LangOpts.Microsoft)
+      Result += "_IMPL";
+    Result += ")";
+  }
+  if (NumIvars > 0) {
+    Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
+    Result += CDecl->getNameAsString();
+    Result += "\n\t";
+  }
+  else
+    Result += ",0";
+  if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
+    Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
+    Result += CDecl->getNameAsString();
+    Result += ", 0\n\t";
+  }
+  else
+    Result += ",0,0";
+  if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+    Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
+    Result += CDecl->getNameAsString();
+    Result += ", 0,0\n";
+  }
+  else
+    Result += ",0,0,0\n";
+  Result += "};\n";
+}
+
+/// RewriteImplementations - This routine rewrites all method implementations
+/// and emits meta-data.
+
+void RewriteObjC::RewriteImplementations() {
+  int ClsDefCount = ClassImplementation.size();
+  int CatDefCount = CategoryImplementation.size();
+
+  // Rewrite implemented methods
+  for (int i = 0; i < ClsDefCount; i++)
+    RewriteImplementationDecl(ClassImplementation[i]);
+
+  for (int i = 0; i < CatDefCount; i++)
+    RewriteImplementationDecl(CategoryImplementation[i]);
+}
+
+void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) {
+  int ClsDefCount = ClassImplementation.size();
+  int CatDefCount = CategoryImplementation.size();
+
+  // This is needed for determining instance variable offsets.
+  Result += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long) &((TYPE *)0)->MEMBER)\n";
+  // For each implemented class, write out all its meta data.
+  for (int i = 0; i < ClsDefCount; i++)
+    RewriteObjCClassMetaData(ClassImplementation[i], Result);
+
+  // For each implemented category, write out all its meta data.
+  for (int i = 0; i < CatDefCount; i++)
+    RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
+
+  // Write objc_symtab metadata
+  /*
+   struct _objc_symtab
+   {
+   long sel_ref_cnt;
+   SEL *refs;
+   short cls_def_cnt;
+   short cat_def_cnt;
+   void *defs[cls_def_cnt + cat_def_cnt];
+   };
+   */
+
+  Result += "\nstruct _objc_symtab {\n";
+  Result += "\tlong sel_ref_cnt;\n";
+  Result += "\tSEL *refs;\n";
+  Result += "\tshort cls_def_cnt;\n";
+  Result += "\tshort cat_def_cnt;\n";
+  Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
+  Result += "};\n\n";
+
+  Result += "static struct _objc_symtab "
+         "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
+  Result += "\t0, 0, " + utostr(ClsDefCount)
+            + ", " + utostr(CatDefCount) + "\n";
+  for (int i = 0; i < ClsDefCount; i++) {
+    Result += "\t,&_OBJC_CLASS_";
+    Result += ClassImplementation[i]->getNameAsString();
+    Result += "\n";
+  }
+
+  for (int i = 0; i < CatDefCount; i++) {
+    Result += "\t,&_OBJC_CATEGORY_";
+    Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
+    Result += "_";
+    Result += CategoryImplementation[i]->getNameAsString();
+    Result += "\n";
+  }
+
+  Result += "};\n\n";
+
+  // Write objc_module metadata
+
+  /*
+   struct _objc_module {
+    long version;
+    long size;
+    const char *name;
+    struct _objc_symtab *symtab;
+   }
+  */
+
+  Result += "\nstruct _objc_module {\n";
+  Result += "\tlong version;\n";
+  Result += "\tlong size;\n";
+  Result += "\tconst char *name;\n";
+  Result += "\tstruct _objc_symtab *symtab;\n";
+  Result += "};\n\n";
+  Result += "static struct _objc_module "
+    "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
+  Result += "\t" + utostr(OBJC_ABI_VERSION) +
+  ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
+  Result += "};\n\n";
+
+  if (LangOpts.Microsoft) {
+    if (ProtocolExprDecls.size()) {
+      Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
+      Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
+      for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
+           E = ProtocolExprDecls.end(); I != E; ++I) {
+        Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
+        Result += (*I)->getNameAsString();
+        Result += " = &_OBJC_PROTOCOL_";
+        Result += (*I)->getNameAsString();
+        Result += ";\n";
+      }
+      Result += "#pragma data_seg(pop)\n\n";
+    }
+    Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
+    Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
+    Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
+    Result += "&_OBJC_MODULES;\n";
+    Result += "#pragma data_seg(pop)\n\n";
+  }
+}
+
+void RewriteObjC::RewriteByRefString(std::string &ResultStr, 
+                                     const std::string &Name,
+                                     ValueDecl *VD) {
+  assert(BlockByRefDeclNo.count(VD) && 
+         "RewriteByRefString: ByRef decl missing");
+  ResultStr += "struct __Block_byref_" + Name + 
+    "_" + utostr(BlockByRefDeclNo[VD]) ;
+}
+
+std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
+                                                   const char *funcName,
+                                                   std::string Tag) {
+  const FunctionType *AFT = CE->getFunctionType();
+  QualType RT = AFT->getResultType();
+  std::string StructRef = "struct " + Tag;
+  std::string S = "static " + RT.getAsString() + " __" +
+                  funcName + "_" + "block_func_" + utostr(i);
+
+  BlockDecl *BD = CE->getBlockDecl();
+
+  if (isa<FunctionNoProtoType>(AFT)) {
+    // No user-supplied arguments. Still need to pass in a pointer to the
+    // block (to reference imported block decl refs).
+    S += "(" + StructRef + " *__cself)";
+  } else if (BD->param_empty()) {
+    S += "(" + StructRef + " *__cself)";
+  } else {
+    const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
+    assert(FT && "SynthesizeBlockFunc: No function proto");
+    S += '(';
+    // first add the implicit argument.
+    S += StructRef + " *__cself, ";
+    std::string ParamStr;
+    for (BlockDecl::param_iterator AI = BD->param_begin(),
+         E = BD->param_end(); AI != E; ++AI) {
+      if (AI != BD->param_begin()) S += ", ";
+      ParamStr = (*AI)->getNameAsString();
+      (*AI)->getType().getAsStringInternal(ParamStr, Context->PrintingPolicy);
+      S += ParamStr;
+    }
+    if (FT->isVariadic()) {
+      if (!BD->param_empty()) S += ", ";
+      S += "...";
+    }
+    S += ')';
+  }
+  S += " {\n";
+
+  // Create local declarations to avoid rewriting all closure decl ref exprs.
+  // First, emit a declaration for all "by ref" decls.
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+       E = BlockByRefDecls.end(); I != E; ++I) {
+    S += "  ";
+    std::string Name = (*I)->getNameAsString();
+    std::string TypeString;
+    RewriteByRefString(TypeString, Name, (*I));
+    TypeString += " *";
+    Name = TypeString + Name;
+    S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
+  }
+  // Next, emit a declaration for all "by copy" declarations.
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+       E = BlockByCopyDecls.end(); I != E; ++I) {
+    S += "  ";
+    std::string Name = (*I)->getNameAsString();
+    // Handle nested closure invocation. For example:
+    //
+    //   void (^myImportedClosure)(void);
+    //   myImportedClosure  = ^(void) { setGlobalInt(x + y); };
+    //
+    //   void (^anotherClosure)(void);
+    //   anotherClosure = ^(void) {
+    //     myImportedClosure(); // import and invoke the closure
+    //   };
+    //
+    if (isTopLevelBlockPointerType((*I)->getType()))
+      S += "struct __block_impl *";
+    else
+      (*I)->getType().getAsStringInternal(Name, Context->PrintingPolicy);
+    S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
+  }
+  std::string RewrittenStr = RewrittenBlockExprs[CE];
+  const char *cstr = RewrittenStr.c_str();
+  while (*cstr++ != '{') ;
+  S += cstr;
+  S += "\n";
+  return S;
+}
+
+std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
+                                                   const char *funcName,
+                                                   std::string Tag) {
+  std::string StructRef = "struct " + Tag;
+  std::string S = "static void __";
+
+  S += funcName;
+  S += "_block_copy_" + utostr(i);
+  S += "(" + StructRef;
+  S += "*dst, " + StructRef;
+  S += "*src) {";
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
+      E = ImportedBlockDecls.end(); I != E; ++I) {
+    S += "_Block_object_assign((void*)&dst->";
+    S += (*I)->getNameAsString();
+    S += ", (void*)src->";
+    S += (*I)->getNameAsString();
+    if (BlockByRefDecls.count((*I)))
+      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
+    else
+      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
+  }
+  S += "}\n";
+  
+  S += "\nstatic void __";
+  S += funcName;
+  S += "_block_dispose_" + utostr(i);
+  S += "(" + StructRef;
+  S += "*src) {";
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
+      E = ImportedBlockDecls.end(); I != E; ++I) {
+    S += "_Block_object_dispose((void*)src->";
+    S += (*I)->getNameAsString();
+    if (BlockByRefDecls.count((*I)))
+      S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
+    else
+      S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
+  }
+  S += "}\n";
+  return S;
+}
+
+std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 
+                                             std::string Desc) {
+  std::string S = "\nstruct " + Tag;
+  std::string Constructor = "  " + Tag;
+
+  S += " {\n  struct __block_impl impl;\n";
+  S += "  struct " + Desc;
+  S += "* Desc;\n";
+
+  Constructor += "(void *fp, "; // Invoke function pointer.
+  Constructor += "struct " + Desc; // Descriptor pointer.
+  Constructor += " *desc";
+
+  if (BlockDeclRefs.size()) {
+    // Output all "by copy" declarations.
+    for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+         E = BlockByCopyDecls.end(); I != E; ++I) {
+      S += "  ";
+      std::string FieldName = (*I)->getNameAsString();
+      std::string ArgName = "_" + FieldName;
+      // Handle nested closure invocation. For example:
+      //
+      //   void (^myImportedBlock)(void);
+      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
+      //
+      //   void (^anotherBlock)(void);
+      //   anotherBlock = ^(void) {
+      //     myImportedBlock(); // import and invoke the closure
+      //   };
+      //
+      if (isTopLevelBlockPointerType((*I)->getType())) {
+        S += "struct __block_impl *";
+        Constructor += ", void *" + ArgName;
+      } else {
+        (*I)->getType().getAsStringInternal(FieldName, Context->PrintingPolicy);
+        (*I)->getType().getAsStringInternal(ArgName, Context->PrintingPolicy);
+        Constructor += ", " + ArgName;
+      }
+      S += FieldName + ";\n";
+    }
+    // Output all "by ref" declarations.
+    for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+         E = BlockByRefDecls.end(); I != E; ++I) {
+      S += "  ";
+      std::string FieldName = (*I)->getNameAsString();
+      std::string ArgName = "_" + FieldName;
+      // Handle nested closure invocation. For example:
+      //
+      //   void (^myImportedBlock)(void);
+      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
+      //
+      //   void (^anotherBlock)(void);
+      //   anotherBlock = ^(void) {
+      //     myImportedBlock(); // import and invoke the closure
+      //   };
+      //
+      if (isTopLevelBlockPointerType((*I)->getType())) {
+        S += "struct __block_impl *";
+        Constructor += ", void *" + ArgName;
+      } else {
+        std::string TypeString;
+        RewriteByRefString(TypeString, FieldName, (*I));
+        TypeString += " *";
+        FieldName = TypeString + FieldName;
+        ArgName = TypeString + ArgName;
+        Constructor += ", " + ArgName;
+      }
+      S += FieldName + "; // by ref\n";
+    }
+    // Finish writing the constructor.
+    Constructor += ", int flags=0) {\n";
+    if (GlobalVarDecl)
+      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
+    else
+      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
+    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
+
+    Constructor += "    Desc = desc;\n";
+
+    // Initialize all "by copy" arguments.
+    for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+         E = BlockByCopyDecls.end(); I != E; ++I) {
+      std::string Name = (*I)->getNameAsString();
+      Constructor += "    ";
+      if (isTopLevelBlockPointerType((*I)->getType()))
+        Constructor += Name + " = (struct __block_impl *)_";
+      else
+        Constructor += Name + " = _";
+      Constructor += Name + ";\n";
+    }
+    // Initialize all "by ref" arguments.
+    for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+         E = BlockByRefDecls.end(); I != E; ++I) {
+      std::string Name = (*I)->getNameAsString();
+      Constructor += "    ";
+      if (isTopLevelBlockPointerType((*I)->getType()))
+        Constructor += Name + " = (struct __block_impl *)_";
+      else
+        Constructor += Name + " = _";
+      Constructor += Name + "->__forwarding;\n";
+    }
+  } else {
+    // Finish writing the constructor.
+    Constructor += ", int flags=0) {\n";
+    if (GlobalVarDecl)
+      Constructor += "    impl.isa = &_NSConcreteGlobalBlock;\n";
+    else
+      Constructor += "    impl.isa = &_NSConcreteStackBlock;\n";
+    Constructor += "    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
+    Constructor += "    Desc = desc;\n";
+  }
+  Constructor += "  ";
+  Constructor += "}\n";
+  S += Constructor;
+  S += "};\n";
+  return S;
+}
+
+std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 
+                                                   std::string ImplTag, int i,
+                                                   const char *FunName,
+                                                   unsigned hasCopy) {
+  std::string S = "\nstatic struct " + DescTag;
+  
+  S += " {\n  unsigned long reserved;\n";
+  S += "  unsigned long Block_size;\n";
+  if (hasCopy) {
+    S += "  void (*copy)(struct ";
+    S += ImplTag; S += "*, struct ";
+    S += ImplTag; S += "*);\n";
+    
+    S += "  void (*dispose)(struct ";
+    S += ImplTag; S += "*);\n";
+  }
+  S += "} ";
+
+  S += DescTag + "_DATA = { 0, sizeof(struct ";
+  S += ImplTag + ")";
+  if (hasCopy) {
+    S += ", __" + std::string(FunName) + "_block_copy_" + utostr(i);
+    S += ", __" + std::string(FunName) + "_block_dispose_" + utostr(i);
+  }
+  S += "};\n";
+  return S;
+}
+
+void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
+                                          const char *FunName) {
+  // Insert declaration for the function in which block literal is used.
+  if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
+    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
+  // Insert closures that were part of the function.
+  for (unsigned i = 0; i < Blocks.size(); i++) {
+
+    CollectBlockDeclRefInfo(Blocks[i]);
+
+    std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
+    std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i);
+
+    std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
+
+    InsertText(FunLocStart, CI.c_str(), CI.size());
+
+    std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
+
+    InsertText(FunLocStart, CF.c_str(), CF.size());
+
+    if (ImportedBlockDecls.size()) {
+      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
+      InsertText(FunLocStart, HF.c_str(), HF.size());
+    }
+    std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
+                                               ImportedBlockDecls.size() > 0);
+    InsertText(FunLocStart, BD.c_str(), BD.size());    
+
+    BlockDeclRefs.clear();
+    BlockByRefDecls.clear();
+    BlockByCopyDecls.clear();
+    BlockCallExprs.clear();
+    ImportedBlockDecls.clear();
+  }
+  Blocks.clear();
+  RewrittenBlockExprs.clear();
+}
+
+void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
+  SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
+  const char *FuncName = FD->getNameAsCString();
+
+  SynthesizeBlockLiterals(FunLocStart, FuncName);
+}
+
+void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
+  //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
+  //SourceLocation FunLocStart = MD->getLocStart();
+  SourceLocation FunLocStart = MD->getLocStart();
+  std::string FuncName = MD->getSelector().getAsString();
+  // Convert colons to underscores.
+  std::string::size_type loc = 0;
+  while ((loc = FuncName.find(":", loc)) != std::string::npos)
+    FuncName.replace(loc, 1, "_");
+
+  SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
+}
+
+void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI) {
+      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+        GetBlockDeclRefExprs(CBE->getBody());
+      else
+        GetBlockDeclRefExprs(*CI);
+    }
+  // Handle specific things.
+  if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
+    // FIXME: Handle enums.
+    if (!isa<FunctionDecl>(CDRE->getDecl()))
+      BlockDeclRefs.push_back(CDRE);
+  return;
+}
+
+void RewriteObjC::GetBlockCallExprs(Stmt *S) {
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI) {
+      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+        GetBlockCallExprs(CBE->getBody());
+      else
+        GetBlockCallExprs(*CI);
+    }
+
+  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+    if (CE->getCallee()->getType()->isBlockPointerType()) {
+      BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
+    }
+  }
+  return;
+}
+
+Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
+  // Navigate to relevant type information.
+  const BlockPointerType *CPT = 0;
+
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
+    CPT = DRE->getType()->getAs<BlockPointerType>();
+  } else if (const BlockDeclRefExpr *CDRE = 
+              dyn_cast<BlockDeclRefExpr>(BlockExp)) {
+    CPT = CDRE->getType()->getAs<BlockPointerType>();
+  } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
+    CPT = MExpr->getType()->getAs<BlockPointerType>();
+  } 
+  else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
+    return SynthesizeBlockCall(Exp, PRE->getSubExpr());
+  }
+  else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 
+    CPT = IEXPR->getType()->getAs<BlockPointerType>();
+  else if (const ConditionalOperator *CEXPR = 
+            dyn_cast<ConditionalOperator>(BlockExp)) {
+    Expr *LHSExp = CEXPR->getLHS();
+    Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
+    Expr *RHSExp = CEXPR->getRHS();
+    Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
+    Expr *CONDExp = CEXPR->getCond();
+    ConditionalOperator *CondExpr =
+      new (Context) ConditionalOperator(CONDExp,
+                                      SourceLocation(), cast<Expr>(LHSStmt),
+                                      SourceLocation(), cast<Expr>(RHSStmt), 
+                                      Exp->getType());
+    return CondExpr;
+  } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
+    CPT = IRE->getType()->getAs<BlockPointerType>();
+  } else {
+    assert(1 && "RewriteBlockClass: Bad type");
+  }
+  assert(CPT && "RewriteBlockClass: Bad type");
+  const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
+  assert(FT && "RewriteBlockClass: Bad type");
+  const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
+  // FTP will be null for closures that don't take arguments.
+
+  RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                      SourceLocation(),
+                                      &Context->Idents.get("__block_impl"));
+  QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
+
+  // Generate a funky cast.
+  llvm::SmallVector<QualType, 8> ArgTypes;
+
+  // Push the block argument type.
+  ArgTypes.push_back(PtrBlock);
+  if (FTP) {
+    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+         E = FTP->arg_type_end(); I && (I != E); ++I) {
+      QualType t = *I;
+      // Make sure we convert "t (^)(...)" to "t (*)(...)".
+      if (isTopLevelBlockPointerType(t)) {
+        const BlockPointerType *BPT = t->getAs<BlockPointerType>();
+        t = Context->getPointerType(BPT->getPointeeType());
+      }
+      ArgTypes.push_back(t);
+    }
+  }
+  // Now do the pointer to function cast.
+  QualType PtrToFuncCastType = Context->getFunctionType(Exp->getType(),
+    &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0);
+
+  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
+
+  CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
+                                               CastExpr::CK_Unknown,
+                                               const_cast<Expr*>(BlockExp));
+  // Don't forget the parens to enforce the proper binding.
+  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+                                          BlkCast);
+  //PE->dump();
+
+  FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+                     &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, 0,
+                                    /*BitWidth=*/0, /*Mutable=*/true);
+  MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
+                                            FD->getType());
+
+  CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
+                                                CastExpr::CK_Unknown, ME);
+  PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
+
+  llvm::SmallVector<Expr*, 8> BlkExprs;
+  // Add the implicit argument.
+  BlkExprs.push_back(BlkCast);
+  // Add the user arguments.
+  for (CallExpr::arg_iterator I = Exp->arg_begin(),
+       E = Exp->arg_end(); I != E; ++I) {
+    BlkExprs.push_back(*I);
+  }
+  CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0],
+                                        BlkExprs.size(),
+                                        Exp->getType(), SourceLocation());
+  return CE;
+}
+
+void RewriteObjC::RewriteBlockCall(CallExpr *Exp) {
+  Stmt *BlockCall = SynthesizeBlockCall(Exp, Exp->getCallee());
+  ReplaceStmt(Exp, BlockCall);
+}
+
+// We need to return the rewritten expression to handle cases where the
+// BlockDeclRefExpr is embedded in another expression being rewritten.
+// For example:
+//
+// int main() {
+//    __block Foo *f;
+//    __block int i;
+//
+//    void (^myblock)() = ^() {
+//        [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
+//        i = 77;
+//    };
+//}
+Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
+  // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 
+  // for each DeclRefExp where BYREFVAR is name of the variable.
+  ValueDecl *VD;
+  bool isArrow = true;
+  if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp))
+    VD = BDRE->getDecl();
+  else {
+    VD = cast<DeclRefExpr>(DeclRefExp)->getDecl();
+    isArrow = false;
+  }
+  
+  FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+                                    &Context->Idents.get("__forwarding"), 
+                                    Context->VoidPtrTy, 0,
+                                    /*BitWidth=*/0, /*Mutable=*/true);
+  MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
+                                            FD, SourceLocation(),
+                                            FD->getType());
+
+  const char *Name = VD->getNameAsCString();
+  FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+                         &Context->Idents.get(Name), 
+                         Context->VoidPtrTy, 0,
+                         /*BitWidth=*/0, /*Mutable=*/true);
+  ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
+                                DeclRefExp->getType());
+  
+  
+  
+  // Need parens to enforce precedence.
+  ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 
+                                          ME);
+  ReplaceStmt(DeclRefExp, PE);
+  return PE;
+}
+
+void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
+  SourceLocation LocStart = CE->getLParenLoc();
+  SourceLocation LocEnd = CE->getRParenLoc();
+
+  // Need to avoid trying to rewrite synthesized casts.
+  if (LocStart.isInvalid())
+    return;
+  // Need to avoid trying to rewrite casts contained in macros.
+  if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
+    return;
+
+  const char *startBuf = SM->getCharacterData(LocStart);
+  const char *endBuf = SM->getCharacterData(LocEnd);
+  QualType QT = CE->getType();
+  const Type* TypePtr = QT->getAs<Type>();
+  if (isa<TypeOfExprType>(TypePtr)) {
+    const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
+    QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
+    std::string TypeAsString = "(";
+    TypeAsString += QT.getAsString();
+    TypeAsString += ")";
+    ReplaceText(LocStart, endBuf-startBuf+1, 
+                TypeAsString.c_str(), TypeAsString.size());
+    return;
+  }
+  // advance the location to startArgList.
+  const char *argPtr = startBuf;
+
+  while (*argPtr++ && (argPtr < endBuf)) {
+    switch (*argPtr) {
+    case '^':
+      // Replace the '^' with '*'.
+      LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf);
+      ReplaceText(LocStart, 1, "*", 1);
+      break;
+    }
+  }
+  return;
+}
+
+void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
+  SourceLocation DeclLoc = FD->getLocation();
+  unsigned parenCount = 0;
+
+  // We have 1 or more arguments that have closure pointers.
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  const char *startArgList = strchr(startBuf, '(');
+
+  assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
+
+  parenCount++;
+  // advance the location to startArgList.
+  DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf);
+  assert((DeclLoc.isValid()) && "Invalid DeclLoc");
+
+  const char *argPtr = startArgList;
+
+  while (*argPtr++ && parenCount) {
+    switch (*argPtr) {
+    case '^':
+      // Replace the '^' with '*'.
+      DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList);
+      ReplaceText(DeclLoc, 1, "*", 1);
+      break;
+    case '(':
+      parenCount++;
+      break;
+    case ')':
+      parenCount--;
+      break;
+    }
+  }
+  return;
+}
+
+bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
+  const FunctionProtoType *FTP;
+  const PointerType *PT = QT->getAs<PointerType>();
+  if (PT) {
+    FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
+  } else {
+    const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
+    assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
+    FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
+  }
+  if (FTP) {
+    for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+         E = FTP->arg_type_end(); I != E; ++I)
+      if (isTopLevelBlockPointerType(*I))
+        return true;
+  }
+  return false;
+}
+
+void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
+                                     const char *&RParen) {
+  const char *argPtr = strchr(Name, '(');
+  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
+
+  LParen = argPtr; // output the start.
+  argPtr++; // skip past the left paren.
+  unsigned parenCount = 1;
+
+  while (*argPtr && parenCount) {
+    switch (*argPtr) {
+    case '(': parenCount++; break;
+    case ')': parenCount--; break;
+    default: break;
+    }
+    if (parenCount) argPtr++;
+  }
+  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
+  RParen = argPtr; // output the end
+}
+
+void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+    RewriteBlockPointerFunctionArgs(FD);
+    return;
+  }
+  // Handle Variables and Typedefs.
+  SourceLocation DeclLoc = ND->getLocation();
+  QualType DeclT;
+  if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+    DeclT = VD->getType();
+  else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
+    DeclT = TDD->getUnderlyingType();
+  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
+    DeclT = FD->getType();
+  else
+    assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
+
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  const char *endBuf = startBuf;
+  // scan backward (from the decl location) for the end of the previous decl.
+  while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
+    startBuf--;
+
+  // *startBuf != '^' if we are dealing with a pointer to function that
+  // may take block argument types (which will be handled below).
+  if (*startBuf == '^') {
+    // Replace the '^' with '*', computing a negative offset.
+    DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
+    ReplaceText(DeclLoc, 1, "*", 1);
+  }
+  if (PointerTypeTakesAnyBlockArguments(DeclT)) {
+    // Replace the '^' with '*' for arguments.
+    DeclLoc = ND->getLocation();
+    startBuf = SM->getCharacterData(DeclLoc);
+    const char *argListBegin, *argListEnd;
+    GetExtentOfArgList(startBuf, argListBegin, argListEnd);
+    while (argListBegin < argListEnd) {
+      if (*argListBegin == '^') {
+        SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
+        ReplaceText(CaretLoc, 1, "*", 1);
+      }
+      argListBegin++;
+    }
+  }
+  return;
+}
+
+
+/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
+/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
+///                    struct Block_byref_id_object *src) {
+///  _Block_object_assign (&_dest->object, _src->object, 
+///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
+///                        [|BLOCK_FIELD_IS_WEAK]) // object
+///  _Block_object_assign(&_dest->object, _src->object, 
+///                       BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
+///                       [|BLOCK_FIELD_IS_WEAK]) // block
+/// }
+/// And:
+/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
+///  _Block_object_dispose(_src->object, 
+///                        BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
+///                        [|BLOCK_FIELD_IS_WEAK]) // object
+///  _Block_object_dispose(_src->object, 
+///                         BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
+///                         [|BLOCK_FIELD_IS_WEAK]) // block
+/// }
+
+std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
+                                                          int flag) {
+  std::string S;
+  if (CopyDestroyCache.count(flag))
+    return S;
+  CopyDestroyCache.insert(flag);
+  S = "static void __Block_byref_id_object_copy_";
+  S += utostr(flag);
+  S += "(void *dst, void *src) {\n";
+  
+  // offset into the object pointer is computed as:
+  // void * + void* + int + int + void* + void *
+  unsigned IntSize = 
+  static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+  unsigned VoidPtrSize = 
+  static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
+  
+  unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/8;
+  S += " _Block_object_assign((char*)dst + ";
+  S += utostr(offset);
+  S += ", *(void * *) ((char*)src + ";
+  S += utostr(offset);
+  S += "), ";
+  S += utostr(flag);
+  S += ");\n}\n";
+  
+  S += "static void __Block_byref_id_object_dispose_";
+  S += utostr(flag);
+  S += "(void *src) {\n";
+  S += " _Block_object_dispose(*(void * *) ((char*)src + ";
+  S += utostr(offset);
+  S += "), ";
+  S += utostr(flag);
+  S += ");\n}\n";
+  return S;
+}
+
+/// RewriteByRefVar - For each __block typex ND variable this routine transforms
+/// the declaration into:
+/// struct __Block_byref_ND {
+/// void *__isa;                  // NULL for everything except __weak pointers
+/// struct __Block_byref_ND *__forwarding;
+/// int32_t __flags;
+/// int32_t __size;
+/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
+/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
+/// typex ND;
+/// };
+///
+/// It then replaces declaration of ND variable with:
+/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 
+///                               __size=sizeof(struct __Block_byref_ND), 
+///                               ND=initializer-if-any};
+///
+///
+void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
+  // Insert declaration for the function in which block literal is
+  // used.
+  if (CurFunctionDeclToDeclareForBlock)
+    RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
+  int flag = 0;
+  int isa = 0;
+  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  SourceLocation X = ND->getLocEnd();
+  X = SM->getInstantiationLoc(X);
+  const char *endBuf = SM->getCharacterData(X);
+  std::string Name(ND->getNameAsString());
+  std::string ByrefType;
+  RewriteByRefString(ByrefType, Name, ND);
+  ByrefType += " {\n";
+  ByrefType += "  void *__isa;\n";
+  RewriteByRefString(ByrefType, Name, ND);
+  ByrefType += " *__forwarding;\n";
+  ByrefType += " int __flags;\n";
+  ByrefType += " int __size;\n";
+  // Add void *__Block_byref_id_object_copy; 
+  // void *__Block_byref_id_object_dispose; if needed.
+  QualType Ty = ND->getType();
+  bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
+  if (HasCopyAndDispose) {
+    ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
+    ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
+  }
+  
+  Ty.getAsStringInternal(Name, Context->PrintingPolicy);
+  ByrefType += " " + Name + ";\n";
+  ByrefType += "};\n";
+  // Insert this type in global scope. It is needed by helper function.
+  SourceLocation FunLocStart;
+  if (CurFunctionDef)
+     FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+  else {
+    assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
+    FunLocStart = CurMethodDef->getLocStart();
+  }
+  InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size());
+  if (Ty.isObjCGCWeak()) {
+    flag |= BLOCK_FIELD_IS_WEAK;
+    isa = 1;
+  }
+  
+  if (HasCopyAndDispose) {
+    flag = BLOCK_BYREF_CALLER;
+    QualType Ty = ND->getType();
+    // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
+    if (Ty->isBlockPointerType())
+      flag |= BLOCK_FIELD_IS_BLOCK;
+    else
+      flag |= BLOCK_FIELD_IS_OBJECT;
+    std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
+    if (!HF.empty())
+      InsertText(FunLocStart, HF.c_str(), HF.size());
+  }
+  
+  // struct __Block_byref_ND ND = 
+  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 
+  //  initializer-if-any};
+  bool hasInit = (ND->getInit() != 0);
+  unsigned flags = 0;
+  if (HasCopyAndDispose)
+    flags |= BLOCK_HAS_COPY_DISPOSE;
+  Name = ND->getNameAsString();
+  ByrefType.clear();
+  RewriteByRefString(ByrefType, Name, ND);
+  std::string ForwardingCastType("(");
+  ForwardingCastType += ByrefType + " *)";
+  if (!hasInit) {
+    ByrefType += " " + Name + " = {(void*)";
+    ByrefType += utostr(isa);
+    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
+    ByrefType += utostr(flags);
+    ByrefType += ", ";
+    ByrefType += "sizeof(";
+    RewriteByRefString(ByrefType, Name, ND);
+    ByrefType += ")";
+    if (HasCopyAndDispose) {
+      ByrefType += ", __Block_byref_id_object_copy_";
+      ByrefType += utostr(flag);
+      ByrefType += ", __Block_byref_id_object_dispose_";
+      ByrefType += utostr(flag);
+    }
+    ByrefType += "};\n";
+    ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), 
+                ByrefType.c_str(), ByrefType.size());
+  }
+  else {
+    SourceLocation startLoc;
+    Expr *E = ND->getInit();
+    if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
+      startLoc = ECE->getLParenLoc();
+    else
+      startLoc = E->getLocStart();
+    startLoc = SM->getInstantiationLoc(startLoc);
+    endBuf = SM->getCharacterData(startLoc);
+   
+    ByrefType += " " + Name;
+    ByrefType += " = {(void*)";
+    ByrefType += utostr(isa);
+    ByrefType += "," +  ForwardingCastType + "&" + Name + ", ";
+    ByrefType += utostr(flags);
+    ByrefType += ", ";
+    ByrefType += "sizeof(";
+    RewriteByRefString(ByrefType, Name, ND);
+    ByrefType += "), ";
+    if (HasCopyAndDispose) {
+      ByrefType += "__Block_byref_id_object_copy_";
+      ByrefType += utostr(flag);
+      ByrefType += ", __Block_byref_id_object_dispose_";
+      ByrefType += utostr(flag);
+      ByrefType += ", ";
+    }
+    ReplaceText(DeclLoc, endBuf-startBuf, 
+                ByrefType.c_str(), ByrefType.size());
+    
+    // Complete the newly synthesized compound expression by inserting a right
+    // curly brace before the end of the declaration.
+    // FIXME: This approach avoids rewriting the initializer expression. It
+    // also assumes there is only one declarator. For example, the following
+    // isn't currently supported by this routine (in general):
+    // 
+    // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
+    //
+    const char *startBuf = SM->getCharacterData(startLoc);
+    const char *semiBuf = strchr(startBuf, ';');
+    assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
+    SourceLocation semiLoc =
+      startLoc.getFileLocWithOffset(semiBuf-startBuf);
+
+    InsertText(semiLoc, "}", 1);
+  }
+  return;
+}
+
+void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
+  // Add initializers for any closure decl refs.
+  GetBlockDeclRefExprs(Exp->getBody());
+  if (BlockDeclRefs.size()) {
+    // Unique all "by copy" declarations.
+    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+      if (!BlockDeclRefs[i]->isByRef())
+        BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
+    // Unique all "by ref" declarations.
+    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+      if (BlockDeclRefs[i]->isByRef()) {
+        BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
+      }
+    // Find any imported blocks...they will need special attention.
+    for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+      if (BlockDeclRefs[i]->isByRef() ||
+          BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 
+          BlockDeclRefs[i]->getType()->isBlockPointerType()) {
+        GetBlockCallExprs(BlockDeclRefs[i]);
+        ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
+      }
+  }
+}
+
+FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(const char *name) {
+  IdentifierInfo *ID = &Context->Idents.get(name);
+  QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
+  return FunctionDecl::Create(*Context, TUDecl,SourceLocation(),
+                              ID, FType, 0, FunctionDecl::Extern, false,
+                              false);
+}
+
+Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
+  Blocks.push_back(Exp);
+
+  CollectBlockDeclRefInfo(Exp);
+  std::string FuncName;
+
+  if (CurFunctionDef)
+    FuncName = CurFunctionDef->getNameAsString();
+  else if (CurMethodDef) {
+    FuncName = CurMethodDef->getSelector().getAsString();
+    // Convert colons to underscores.
+    std::string::size_type loc = 0;
+    while ((loc = FuncName.find(":", loc)) != std::string::npos)
+      FuncName.replace(loc, 1, "_");
+  } else if (GlobalVarDecl)
+    FuncName = std::string(GlobalVarDecl->getNameAsString());
+
+  std::string BlockNumber = utostr(Blocks.size()-1);
+
+  std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
+  std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
+
+  // Get a pointer to the function type so we can cast appropriately.
+  QualType FType = Context->getPointerType(QualType(Exp->getFunctionType(),0));
+
+  FunctionDecl *FD;
+  Expr *NewRep;
+
+  // Simulate a contructor call...
+  FD = SynthBlockInitFunctionDecl(Tag.c_str());
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, SourceLocation());
+
+  llvm::SmallVector<Expr*, 4> InitExprs;
+
+  // Initialize the block function.
+  FD = SynthBlockInitFunctionDecl(Func.c_str());
+  DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(),
+                                               SourceLocation());
+  CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+                                                CastExpr::CK_Unknown, Arg);
+  InitExprs.push_back(castExpr);
+
+  // Initialize the block descriptor.
+  std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
+
+  VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 
+                                    &Context->Idents.get(DescData.c_str()), 
+                                    Context->VoidPtrTy, 0,
+                                    VarDecl::Static);
+  UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
+                                  new (Context) DeclRefExpr(NewVD, 
+                                    Context->VoidPtrTy, SourceLocation()), 
+                                  UnaryOperator::AddrOf,
+                                  Context->getPointerType(Context->VoidPtrTy), 
+                                  SourceLocation());
+  InitExprs.push_back(DescRefExpr); 
+  
+  // Add initializers for any closure decl refs.
+  if (BlockDeclRefs.size()) {
+    Expr *Exp;
+    // Output all "by copy" declarations.
+    for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+         E = BlockByCopyDecls.end(); I != E; ++I) {
+      if (isObjCType((*I)->getType())) {
+        // FIXME: Conform to ABI ([[obj retain] autorelease]).
+        FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+        Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
+      } else if (isTopLevelBlockPointerType((*I)->getType())) {
+        FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+        Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
+        Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+                                       CastExpr::CK_Unknown, Arg);
+      } else {
+        FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+        Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
+      }
+      InitExprs.push_back(Exp);
+    }
+    // Output all "by ref" declarations.
+    for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+         E = BlockByRefDecls.end(); I != E; ++I) {
+      ValueDecl *ND = (*I);
+      std::string Name(ND->getNameAsString());
+      std::string RecName;
+      RewriteByRefString(RecName, Name, ND);
+      IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 
+                                                + sizeof("struct"));
+      RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                          SourceLocation(), II);
+      assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
+      QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+      
+      FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+      Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
+      Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf,
+                              Context->getPointerType(Exp->getType()),
+                              SourceLocation());
+      Exp = NoTypeInfoCStyleCastExpr(Context, castT, CastExpr::CK_Unknown, Exp);
+      InitExprs.push_back(Exp);
+    }
+  }
+  if (ImportedBlockDecls.size()) {
+    // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
+    int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
+    unsigned IntSize = 
+      static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+    Expr *FlagExp = new (Context) IntegerLiteral(llvm::APInt(IntSize, flag), 
+                                             Context->IntTy, SourceLocation());
+    InitExprs.push_back(FlagExp);
+  }
+  NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
+                                  FType, SourceLocation());
+  NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf,
+                             Context->getPointerType(NewRep->getType()),
+                             SourceLocation());
+  NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CastExpr::CK_Unknown,
+                                    NewRep);
+  BlockDeclRefs.clear();
+  BlockByRefDecls.clear();
+  BlockByCopyDecls.clear();
+  ImportedBlockDecls.clear();
+  return NewRep;
+}
+
+//===----------------------------------------------------------------------===//
+// Function Body / Expression rewriting
+//===----------------------------------------------------------------------===//
+
+// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer().
+// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with
+// their respective BinaryOperator. Without this knowledge, we'd need to rewrite
+// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter).
+// Since the rewriter isn't capable of rewriting rewritten code, it's important
+// we get this right.
+void RewriteObjC::CollectPropertySetters(Stmt *S) {
+  // Perform a bottom up traversal of all children.
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI)
+      CollectPropertySetters(*CI);
+
+  if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
+    if (BinOp->isAssignmentOp()) {
+      if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()))
+        PropSetters[PRE] = BinOp;
+    }
+  }
+}
+
+Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
+  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+      isa<DoStmt>(S) || isa<ForStmt>(S))
+    Stmts.push_back(S);
+  else if (isa<ObjCForCollectionStmt>(S)) {
+    Stmts.push_back(S);
+    ObjCBcLabelNo.push_back(++BcLabelCount);
+  }
+
+  SourceRange OrigStmtRange = S->getSourceRange();
+
+  // Perform a bottom up rewrite of all children.
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI) {
+      Stmt *newStmt;
+      Stmt *S = (*CI);
+      if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
+        Expr *OldBase = IvarRefExpr->getBase();
+        bool replaced = false;
+        newStmt = RewriteObjCNestedIvarRefExpr(S, replaced);
+        if (replaced) {
+          if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt))
+            ReplaceStmt(OldBase, IRE->getBase());
+          else
+            ReplaceStmt(S, newStmt);
+        }
+      }
+      else
+        newStmt = RewriteFunctionBodyOrGlobalInitializer(S);
+      if (newStmt)
+        *CI = newStmt;
+    }
+
+  if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+    // Rewrite the block body in place.
+    RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
+
+    // Now we snarf the rewritten text and stash it away for later use.
+    std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
+    RewrittenBlockExprs[BE] = Str;
+
+    Stmt *blockTranscribed = SynthBlockInitExpr(BE);
+    //blockTranscribed->dump();
+    ReplaceStmt(S, blockTranscribed);
+    return blockTranscribed;
+  }
+  // Handle specific things.
+  if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
+    return RewriteAtEncode(AtEncode);
+
+  if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) {
+    BinaryOperator *BinOp = PropSetters[PropRefExpr];
+    if (BinOp) {
+      // Because the rewriter doesn't allow us to rewrite rewritten code,
+      // we need to rewrite the right hand side prior to rewriting the setter.
+      DisableReplaceStmt = true;
+      // Save the source range. Even if we disable the replacement, the
+      // rewritten node will have been inserted into the tree. If the synthesized
+      // node is at the 'end', the rewriter will fail. Consider this:
+      //    self.errorHandler = handler ? handler :
+      //              ^(NSURL *errorURL, NSError *error) { return (BOOL)1; };
+      SourceRange SrcRange = BinOp->getSourceRange();
+      Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());
+      DisableReplaceStmt = false;
+      //
+      // Unlike the main iterator, we explicily avoid changing 'BinOp'. If
+      // we changed the RHS of BinOp, the rewriter would fail (since it needs
+      // to see the original expression). Consider this example:
+      //
+      // Foo *obj1, *obj2;
+      //
+      // obj1.i = [obj2 rrrr];
+      //
+      // 'BinOp' for the previous expression looks like:
+      //
+      // (BinaryOperator 0x231ccf0 'int' '='
+      //   (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i"
+      //     (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0))
+      //   (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr
+      //     (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0)))
+      //
+      // 'newStmt' represents the rewritten message expression. For example:
+      //
+      // (CallExpr 0x231d300 'id':'struct objc_object *'
+      //   (ParenExpr 0x231d2e0 'int (*)(id, SEL)'
+      //     (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)'
+      //       (CStyleCastExpr 0x231d220 'void *'
+      //         (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0))))
+      //
+      // Note that 'newStmt' is passed to RewritePropertySetter so that it
+      // can be used as the setter argument. ReplaceStmt() will still 'see'
+      // the original RHS (since we haven't altered BinOp).
+      //
+      // This implies the Rewrite* routines can no longer delete the original
+      // node. As a result, we now leak the original AST nodes.
+      //
+      return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);
+    } else {
+      return RewritePropertyGetter(PropRefExpr);
+    }
+  }
+  if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
+    return RewriteAtSelector(AtSelector);
+
+  if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
+    return RewriteObjCStringLiteral(AtString);
+
+  if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
+#if 0
+    // Before we rewrite it, put the original message expression in a comment.
+    SourceLocation startLoc = MessExpr->getLocStart();
+    SourceLocation endLoc = MessExpr->getLocEnd();
+
+    const char *startBuf = SM->getCharacterData(startLoc);
+    const char *endBuf = SM->getCharacterData(endLoc);
+
+    std::string messString;
+    messString += "// ";
+    messString.append(startBuf, endBuf-startBuf+1);
+    messString += "\n";
+
+    // FIXME: Missing definition of
+    // InsertText(clang::SourceLocation, char const*, unsigned int).
+    // InsertText(startLoc, messString.c_str(), messString.size());
+    // Tried this, but it didn't work either...
+    // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
+#endif
+    return RewriteMessageExpr(MessExpr);
+  }
+
+  if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
+    return RewriteObjCTryStmt(StmtTry);
+
+  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
+    return RewriteObjCSynchronizedStmt(StmtTry);
+
+  if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
+    return RewriteObjCThrowStmt(StmtThrow);
+
+  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
+    return RewriteObjCProtocolExpr(ProtocolExp);
+
+  if (ObjCForCollectionStmt *StmtForCollection =
+        dyn_cast<ObjCForCollectionStmt>(S))
+    return RewriteObjCForCollectionStmt(StmtForCollection,
+                                        OrigStmtRange.getEnd());
+  if (BreakStmt *StmtBreakStmt =
+      dyn_cast<BreakStmt>(S))
+    return RewriteBreakStmt(StmtBreakStmt);
+  if (ContinueStmt *StmtContinueStmt =
+      dyn_cast<ContinueStmt>(S))
+    return RewriteContinueStmt(StmtContinueStmt);
+
+  // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
+  // and cast exprs.
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+    // FIXME: What we're doing here is modifying the type-specifier that
+    // precedes the first Decl.  In the future the DeclGroup should have
+    // a separate type-specifier that we can rewrite.
+    // NOTE: We need to avoid rewriting the DeclStmt if it is within
+    // the context of an ObjCForCollectionStmt. For example:
+    //   NSArray *someArray;
+    //   for (id <FooProtocol> index in someArray) ;
+    // This is because RewriteObjCForCollectionStmt() does textual rewriting 
+    // and it depends on the original text locations/positions.
+    if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+      RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
+
+    // Blocks rewrite rules.
+    for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+         DI != DE; ++DI) {
+      Decl *SD = *DI;
+      if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
+        if (isTopLevelBlockPointerType(ND->getType()))
+          RewriteBlockPointerDecl(ND);
+        else if (ND->getType()->isFunctionPointerType())
+          CheckFunctionPointerDecl(ND->getType(), ND);
+        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) 
+          if (VD->hasAttr<BlocksAttr>()) {
+            static unsigned uniqueByrefDeclCount = 0;
+            assert(!BlockByRefDeclNo.count(ND) &&
+              "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
+            BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
+            RewriteByRefVar(VD);
+          }
+      }
+      if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+        if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
+          RewriteBlockPointerDecl(TD);
+        else if (TD->getUnderlyingType()->isFunctionPointerType())
+          CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+      }
+    }
+  }
+
+  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
+    RewriteObjCQualifiedInterfaceTypes(CE);
+
+  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+      isa<DoStmt>(S) || isa<ForStmt>(S)) {
+    assert(!Stmts.empty() && "Statement stack is empty");
+    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
+             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
+            && "Statement stack mismatch");
+    Stmts.pop_back();
+  }
+  // Handle blocks rewriting.
+  if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+    if (BDRE->isByRef())
+      return RewriteBlockDeclRefExpr(BDRE);
+  }
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+    ValueDecl *VD = DRE->getDecl(); 
+    if (VD->hasAttr<BlocksAttr>())
+      return RewriteBlockDeclRefExpr(DRE);
+  }
+  
+  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+    if (CE->getCallee()->getType()->isBlockPointerType()) {
+      Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
+      ReplaceStmt(S, BlockCall);
+      return BlockCall;
+    }
+  }
+  if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
+    RewriteCastExpr(CE);
+  }
+#if 0
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
+    CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
+    // Get the new text.
+    std::string SStr;
+    llvm::raw_string_ostream Buf(SStr);
+    Replacement->printPretty(Buf, *Context);
+    const std::string &Str = Buf.str();
+
+    printf("CAST = %s\n", &Str[0]);
+    InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+    delete S;
+    return Replacement;
+  }
+#endif
+  // Return this stmt unmodified.
+  return S;
+}
+
+void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
+  for (RecordDecl::field_iterator i = RD->field_begin(), 
+                                  e = RD->field_end(); i != e; ++i) {
+    FieldDecl *FD = *i;
+    if (isTopLevelBlockPointerType(FD->getType()))
+      RewriteBlockPointerDecl(FD);
+    if (FD->getType()->isObjCQualifiedIdType() ||
+        FD->getType()->isObjCQualifiedInterfaceType())
+      RewriteObjCQualifiedInterfaceTypes(FD);
+  }
+}
+
+/// HandleDeclInMainFile - This is called for each top-level decl defined in the
+/// main file of the input.
+void RewriteObjC::HandleDeclInMainFile(Decl *D) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->isOverloadedOperator())
+      return;
+
+    // Since function prototypes don't have ParmDecl's, we check the function
+    // prototype. This enables us to rewrite function declarations and
+    // definitions using the same code.
+    RewriteBlocksInFunctionProtoType(FD->getType(), FD);
+
+    // FIXME: If this should support Obj-C++, support CXXTryStmt
+    if (CompoundStmt *Body = FD->getCompoundBody()) {
+      CurFunctionDef = FD;
+      CurFunctionDeclToDeclareForBlock = FD;
+      CollectPropertySetters(Body);
+      CurrentBody = Body;
+      Body =
+       cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
+      FD->setBody(Body);
+      CurrentBody = 0;
+      if (PropParentMap) {
+        delete PropParentMap;
+        PropParentMap = 0;
+      }
+      // This synthesizes and inserts the block "impl" struct, invoke function,
+      // and any copy/dispose helper functions.
+      InsertBlockLiteralsWithinFunction(FD);
+      CurFunctionDef = 0;
+      CurFunctionDeclToDeclareForBlock = 0;
+    }
+    return;
+  }
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    if (CompoundStmt *Body = MD->getCompoundBody()) {
+      CurMethodDef = MD;
+      CollectPropertySetters(Body);
+      CurrentBody = Body;
+      Body =
+       cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
+      MD->setBody(Body);
+      CurrentBody = 0;
+      if (PropParentMap) {
+        delete PropParentMap;
+        PropParentMap = 0;
+      }
+      InsertBlockLiteralsWithinMethod(MD);
+      CurMethodDef = 0;
+    }
+  }
+  if (ObjCImplementationDecl *CI = dyn_cast<ObjCImplementationDecl>(D))
+    ClassImplementation.push_back(CI);
+  else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D))
+    CategoryImplementation.push_back(CI);
+  else if (ObjCClassDecl *CD = dyn_cast<ObjCClassDecl>(D))
+    RewriteForwardClassDecl(CD);
+  else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    RewriteObjCQualifiedInterfaceTypes(VD);
+    if (isTopLevelBlockPointerType(VD->getType()))
+      RewriteBlockPointerDecl(VD);
+    else if (VD->getType()->isFunctionPointerType()) {
+      CheckFunctionPointerDecl(VD->getType(), VD);
+      if (VD->getInit()) {
+        if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
+          RewriteCastExpr(CE);
+        }
+      }
+    } else if (VD->getType()->isRecordType()) {
+      RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
+      if (RD->isDefinition())
+        RewriteRecordBody(RD);
+    }
+    if (VD->getInit()) {
+      GlobalVarDecl = VD;
+      CollectPropertySetters(VD->getInit());
+      CurrentBody = VD->getInit();
+      RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
+      CurrentBody = 0;
+      if (PropParentMap) {
+        delete PropParentMap;
+        PropParentMap = 0;
+      }
+      SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
+                              VD->getNameAsCString());
+      GlobalVarDecl = 0;
+
+      // This is needed for blocks.
+      if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
+        RewriteCastExpr(CE);
+      }
+    }
+    return;
+  }
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
+      RewriteBlockPointerDecl(TD);
+    else if (TD->getUnderlyingType()->isFunctionPointerType())
+      CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+    else if (TD->getUnderlyingType()->isRecordType()) {
+      RecordDecl *RD = TD->getUnderlyingType()->getAs<RecordType>()->getDecl();
+      if (RD->isDefinition())
+        RewriteRecordBody(RD);
+    }
+    return;
+  }
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
+    if (RD->isDefinition()) 
+      RewriteRecordBody(RD);
+    return;
+  }
+  // Nothing yet.
+}
+
+void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
+  if (Diags.hasErrorOccurred())
+    return;
+
+  RewriteInclude();
+
+  // Here's a great place to add any extra declarations that may be needed.
+  // Write out meta data for each @protocol(<expr>).
+  for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
+       E = ProtocolExprDecls.end(); I != E; ++I)
+    RewriteObjCProtocolMetaData(*I, "", "", Preamble);
+
+  InsertText(SM->getLocForStartOfFile(MainFileID),
+             Preamble.c_str(), Preamble.size(), false);
+  if (ClassImplementation.size() || CategoryImplementation.size())
+    RewriteImplementations();
+
+  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
+  // we are done.
+  if (const RewriteBuffer *RewriteBuf =
+      Rewrite.getRewriteBufferFor(MainFileID)) {
+    //printf("Changed:\n");
+    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
+  } else {
+    fprintf(stderr, "No changes\n");
+  }
+
+  if (ClassImplementation.size() || CategoryImplementation.size() ||
+      ProtocolExprDecls.size()) {
+    // Rewrite Objective-c meta data*
+    std::string ResultStr;
+    SynthesizeMetaDataIntoBuffer(ResultStr);
+    // Emit metadata.
+    *OutFile << ResultStr;
+  }
+  OutFile->flush();
+}
+
diff --git a/lib/Frontend/RewriteTest.cpp b/lib/Frontend/RewriteTest.cpp
new file mode 100644
index 0000000..0414678
--- /dev/null
+++ b/lib/Frontend/RewriteTest.cpp
@@ -0,0 +1,39 @@
+//===--- RewriteTest.cpp - Rewriter playground ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a testbed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/TokenRewriter.h"
+#include "llvm/Support/raw_ostream.h"
+
+void clang::DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS) {
+  SourceManager &SM = PP.getSourceManager();
+  const LangOptions &LangOpts = PP.getLangOptions();
+
+  TokenRewriter Rewriter(SM.getMainFileID(), SM, LangOpts);
+
+  // Throw <i> </i> tags around comments.
+  for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
+       E = Rewriter.token_end(); I != E; ++I) {
+    if (I->isNot(tok::comment)) continue;
+
+    Rewriter.AddTokenBefore(I, "<i>");
+    Rewriter.AddTokenAfter(I, "</i>");
+  }
+
+
+  // Print out the output.
+  for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
+       E = Rewriter.token_end(); I != E; ++I)
+    *OS << PP.getSpelling(*I);
+}
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
new file mode 100644
index 0000000..ce474d3
--- /dev/null
+++ b/lib/Frontend/StmtXML.cpp
@@ -0,0 +1,448 @@
+//===--- StmtXML.cpp - XML implementation for Stmt ASTs ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dumpXML methods, which dump out the
+// AST to an XML document.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// StmtXML Visitor
+//===----------------------------------------------------------------------===//
+
+namespace  {
+  class StmtXML : public StmtVisitor<StmtXML> {
+    DocumentXML&  Doc;
+
+    //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+    //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+  void addSpecialAttribute(const char* pName, StringLiteral* Str) {
+    Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+  }
+
+  void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) {
+    if (S->isArgumentType())
+      Doc.addAttribute(pName, S->getArgumentType());
+  }
+
+  void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) {
+    if (S->isTypeOperand())
+      Doc.addAttribute(pName, S->getTypeOperand());
+  }
+
+
+  public:
+    StmtXML(DocumentXML& doc)
+      : Doc(doc) {
+    }
+
+    void DumpSubTree(Stmt *S) {
+      if (S) {
+        Visit(S);
+        if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+          for (DeclStmt::decl_iterator DI = DS->decl_begin(),
+                 DE = DS->decl_end(); DI != DE; ++DI) {
+            Doc.PrintDecl(*DI);
+          }
+        } else {
+          for (Stmt::child_iterator i = S->child_begin(), e = S->child_end();
+               i != e; ++i)
+            DumpSubTree(*i);
+        }
+        Doc.toParent();
+      } else {
+        Doc.addSubNode("NULL").toParent();
+      }
+    }
+
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* S)            \
+  {                                      \
+    typedef CLASS tStmtType;             \
+    Doc.addSubNode(NAME);
+
+#define ATTRIBUTE_XML( FN, NAME )         Doc.addAttribute(NAME, S->FN);
+#define TYPE_ATTRIBUTE_XML( FN )          ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME )     Doc.addAttributeOptional(NAME, S->FN);
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
+#define ATTRIBUTE_FILE_LOCATION_XML       Doc.addLocationRange(S->getSourceRange());
+
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = false;        \
+    switch (S->FN) {                    \
+    default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  \
+  {                                         \
+    const char* pAttributeName = NAME;      \
+    const bool optional = true;             \
+    switch (S->FN) {                        \
+    default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME )         case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML                    } }
+#define END_NODE_XML                    }
+
+#define ID_ATTRIBUTE_XML                Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
+    // Stmts.
+    void VisitStmt(Stmt *Node);
+    void VisitDeclStmt(DeclStmt *Node);
+    void VisitLabelStmt(LabelStmt *Node);
+    void VisitGotoStmt(GotoStmt *Node);
+
+    // Exprs
+    void VisitExpr(Expr *Node);
+    void VisitDeclRefExpr(DeclRefExpr *Node);
+    void VisitPredefinedExpr(PredefinedExpr *Node);
+    void VisitCharacterLiteral(CharacterLiteral *Node);
+    void VisitIntegerLiteral(IntegerLiteral *Node);
+    void VisitFloatingLiteral(FloatingLiteral *Node);
+    void VisitStringLiteral(StringLiteral *Str);
+    void VisitUnaryOperator(UnaryOperator *Node);
+    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
+    void VisitMemberExpr(MemberExpr *Node);
+    void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
+    void VisitBinaryOperator(BinaryOperator *Node);
+    void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
+    void VisitAddrLabelExpr(AddrLabelExpr *Node);
+    void VisitTypesCompatibleExpr(TypesCompatibleExpr *Node);
+
+    // C++
+    void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
+    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
+    void VisitCXXThisExpr(CXXThisExpr *Node);
+    void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
+
+    // ObjC
+    void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
+    void VisitObjCMessageExpr(ObjCMessageExpr* Node);
+    void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
+    void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
+    void VisitObjCImplicitSetterGetterRefExpr(
+                        ObjCImplicitSetterGetterRefExpr *Node);
+    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
+    void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+#endif
+  };
+}
+
+//===----------------------------------------------------------------------===//
+//  Stmt printing methods.
+//===----------------------------------------------------------------------===//
+#if (0)
+void StmtXML::VisitStmt(Stmt *Node) {
+  // nothing special to do
+}
+
+void StmtXML::VisitDeclStmt(DeclStmt *Node) {
+  for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
+       DI != DE; ++DI) {
+    Doc.PrintDecl(*DI);
+  }
+}
+
+void StmtXML::VisitLabelStmt(LabelStmt *Node) {
+  Doc.addAttribute("name", Node->getName());
+}
+
+void StmtXML::VisitGotoStmt(GotoStmt *Node) {
+  Doc.addAttribute("name", Node->getLabel()->getName());
+}
+
+//===----------------------------------------------------------------------===//
+//  Expr printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitExpr(Expr *Node) {
+  DumpExpr(Node);
+}
+
+void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
+  DumpExpr(Node);
+
+  const char* pKind;
+  switch (Node->getDecl()->getKind()) {
+  case Decl::Function: pKind = "FunctionDecl"; break;
+  case Decl::Var: pKind = "Var"; break;
+  case Decl::ParmVar: pKind = "ParmVar"; break;
+  case Decl::EnumConstant: pKind = "EnumConstant"; break;
+  case Decl::Typedef: pKind = "Typedef"; break;
+  case Decl::Record: pKind = "Record"; break;
+  case Decl::Enum: pKind = "Enum"; break;
+  case Decl::CXXRecord: pKind = "CXXRecord"; break;
+  case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
+  case Decl::ObjCClass: pKind = "ObjCClass"; break;
+  default: pKind = "Decl"; break;
+  }
+
+  Doc.addAttribute("kind", pKind);
+  Doc.addAttribute("name", Node->getDecl()->getNameAsString());
+  Doc.addRefAttribute(Node->getDecl());
+}
+
+void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) {
+  DumpExpr(Node);
+  switch (Node->getIdentType()) {
+  default: assert(0 && "unknown case");
+  case PredefinedExpr::Func:           Doc.addAttribute("predefined", " __func__"); break;
+  case PredefinedExpr::Function:       Doc.addAttribute("predefined", " __FUNCTION__"); break;
+  case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
+  }
+}
+
+void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("value", Node->getValue());
+}
+
+void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) {
+  DumpExpr(Node);
+  bool isSigned = Node->getType()->isSignedIntegerType();
+  Doc.addAttribute("value", Node->getValue().toString(10, isSigned));
+}
+
+void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) {
+  DumpExpr(Node);
+  // FIXME: output float as written in source (no approximation or the like)
+  //Doc.addAttribute("value", Node->getValueAsApproximateDouble()));
+  Doc.addAttribute("value", "FIXME");
+}
+
+void StmtXML::VisitStringLiteral(StringLiteral *Str) {
+  DumpExpr(Str);
+  if (Str->isWide())
+    Doc.addAttribute("is_wide", "1");
+
+  Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+}
+
+
+const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) {
+  switch (Op) {
+  default: assert(0 && "Unknown unary operator");
+  case UnaryOperator::PostInc: return "postinc";
+  case UnaryOperator::PostDec: return "postdec";
+  case UnaryOperator::PreInc:  return "preinc";
+  case UnaryOperator::PreDec:  return "predec";
+  case UnaryOperator::AddrOf:  return "addrof";
+  case UnaryOperator::Deref:   return "deref";
+  case UnaryOperator::Plus:    return "plus";
+  case UnaryOperator::Minus:   return "minus";
+  case UnaryOperator::Not:     return "not";
+  case UnaryOperator::LNot:    return "lnot";
+  case UnaryOperator::Real:    return "__real";
+  case UnaryOperator::Imag:    return "__imag";
+  case UnaryOperator::Extension: return "__extension__";
+  case UnaryOperator::OffsetOf: return "__builtin_offsetof";
+  }
+}
+
+
+const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) {
+  switch (Op) {
+  default: assert(0 && "Unknown binary operator");
+  case BinaryOperator::PtrMemD:   return "ptrmemd";
+  case BinaryOperator::PtrMemI:   return "ptrmemi";
+  case BinaryOperator::Mul:       return "mul";
+  case BinaryOperator::Div:       return "div";
+  case BinaryOperator::Rem:       return "rem";
+  case BinaryOperator::Add:       return "add";
+  case BinaryOperator::Sub:       return "sub";
+  case BinaryOperator::Shl:       return "shl";
+  case BinaryOperator::Shr:       return "shr";
+  case BinaryOperator::LT:        return "lt";
+  case BinaryOperator::GT:        return "gt";
+  case BinaryOperator::LE:        return "le";
+  case BinaryOperator::GE:        return "ge";
+  case BinaryOperator::EQ:        return "eq";
+  case BinaryOperator::NE:        return "ne";
+  case BinaryOperator::And:       return "and";
+  case BinaryOperator::Xor:       return "xor";
+  case BinaryOperator::Or:        return "or";
+  case BinaryOperator::LAnd:      return "land";
+  case BinaryOperator::LOr:       return "lor";
+  case BinaryOperator::Assign:    return "assign";
+  case BinaryOperator::MulAssign: return "mulassign";
+  case BinaryOperator::DivAssign: return "divassign";
+  case BinaryOperator::RemAssign: return "remassign";
+  case BinaryOperator::AddAssign: return "addassign";
+  case BinaryOperator::SubAssign: return "subassign";
+  case BinaryOperator::ShlAssign: return "shlassign";
+  case BinaryOperator::ShrAssign: return "shrassign";
+  case BinaryOperator::AndAssign: return "andassign";
+  case BinaryOperator::XorAssign: return "xorassign";
+  case BinaryOperator::OrAssign:  return "orassign";
+  case BinaryOperator::Comma:     return "comma";
+  }
+}
+
+void StmtXML::VisitUnaryOperator(UnaryOperator *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
+}
+
+void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof");
+  Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0");
+  if (Node->isArgumentType())
+    DumpTypeExpr(Node->getArgumentType());
+}
+
+void StmtXML::VisitMemberExpr(MemberExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0");
+  Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString());
+  Doc.addRefAttribute(Node->getMemberDecl());
+}
+
+void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("name", Node->getAccessor().getName());
+}
+
+void StmtXML::VisitBinaryOperator(BinaryOperator *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
+}
+
+void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
+  VisitBinaryOperator(Node);
+/* FIXME: is this needed in the AST?
+  DumpExpr(Node);
+  CurrentNode = CurrentNode->addSubNode("ComputeLHSTy");
+  DumpType(Node->getComputationLHSType());
+  CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy");
+  DumpType(Node->getComputationResultType());
+  Doc.toParent();
+*/
+}
+
+// GNU extensions.
+
+void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("name", Node->getLabel()->getName());
+}
+
+void StmtXML::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
+  DumpExpr(Node);
+  DumpTypeExpr(Node->getArgType1());
+  DumpTypeExpr(Node->getArgType2());
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("kind", Node->getCastName());
+  DumpTypeExpr(Node->getTypeAsWritten());
+}
+
+void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("value", Node->getValue() ? "true" : "false");
+}
+
+void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) {
+  DumpExpr(Node);
+}
+
+void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
+  DumpExpr(Node);
+  DumpTypeExpr(Node->getTypeAsWritten());
+}
+
+//===----------------------------------------------------------------------===//
+// Obj-C Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("selector", Node->getSelector().getAsString());
+  IdentifierInfo* clsName = Node->getClassName();
+  if (clsName)
+    Doc.addAttribute("class", clsName->getName());
+}
+
+void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
+  DumpExpr(Node);
+  DumpTypeExpr(Node->getEncodedType());
+}
+
+void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("selector", Node->getSelector().getAsString());
+}
+
+void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("protocol", Node->getProtocol()->getNameAsString());
+}
+
+void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("property", Node->getProperty()->getNameAsString());
+}
+
+void StmtXML::VisitObjCImplicitSetterGetterRefExpr(
+                             ObjCImplicitSetterGetterRefExpr *Node) {
+  DumpExpr(Node);
+  ObjCMethodDecl *Getter = Node->getGetterMethod();
+  ObjCMethodDecl *Setter = Node->getSetterMethod();
+  Doc.addAttribute("Getter", Getter->getSelector().getAsString());
+  Doc.addAttribute("Setter", Setter ? Setter->getSelector().getAsString().c_str() : "(null)");
+}
+
+void StmtXML::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("super", "1");
+}
+
+void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("kind", Node->getDecl()->getDeclKindName());
+  Doc.addAttribute("decl", Node->getDecl()->getNameAsString());
+  if (Node->isFreeIvar())
+    Doc.addAttribute("isFreeIvar", "1");
+}
+#endif
+//===----------------------------------------------------------------------===//
+// Stmt method implementations
+//===----------------------------------------------------------------------===//
+
+/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+void DocumentXML::PrintStmt(const Stmt *S) {
+  StmtXML P(*this);
+  P.DumpSubTree(const_cast<Stmt*>(S));
+}
+
diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp
new file mode 100644
index 0000000..fdf2ec8
--- /dev/null
+++ b/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -0,0 +1,48 @@
+//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+
+/// HandleDiagnostic - Store the errors, warnings, and notes that are
+/// reported.
+///
+void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
+                                            const DiagnosticInfo &Info) {
+  llvm::SmallString<100> Buf;
+  Info.FormatDiagnostic(Buf);
+  switch (Level) {
+  default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
+  case Diagnostic::Note:
+    Notes.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+    break;
+  case Diagnostic::Warning:
+    Warnings.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+    break;
+  case Diagnostic::Error:
+  case Diagnostic::Fatal:
+    Errors.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+    break;
+  }
+}
+
+void TextDiagnosticBuffer::FlushDiagnostics(Diagnostic &Diags) const {
+  // FIXME: Flush the diagnostics in order.
+  for (const_iterator it = err_begin(), ie = err_end(); it != ie; ++it)
+    Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, it->second.c_str()));
+  for (const_iterator it = warn_begin(), ie = warn_end(); it != ie; ++it)
+    Diags.Report(Diags.getCustomDiagID(Diagnostic::Warning,it->second.c_str()));
+  for (const_iterator it = note_begin(), ie = note_end(); it != ie; ++it)
+    Diags.Report(Diags.getCustomDiagID(Diagnostic::Note, it->second.c_str()));
+}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
new file mode 100644
index 0000000..83b4542
--- /dev/null
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -0,0 +1,852 @@
+//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This diagnostic client prints out their diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/SmallString.h"
+#include <algorithm>
+using namespace clang;
+
+static const enum llvm::raw_ostream::Colors noteColor =
+  llvm::raw_ostream::BLACK;
+static const enum llvm::raw_ostream::Colors fixitColor =
+  llvm::raw_ostream::GREEN;
+static const enum llvm::raw_ostream::Colors caretColor =
+  llvm::raw_ostream::GREEN;
+static const enum llvm::raw_ostream::Colors warningColor =
+  llvm::raw_ostream::MAGENTA;
+static const enum llvm::raw_ostream::Colors errorColor = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors fatalColor = llvm::raw_ostream::RED;
+// used for changing only the bold attribute
+static const enum llvm::raw_ostream::Colors savedColor =
+  llvm::raw_ostream::SAVEDCOLOR;
+
+/// \brief Number of spaces to indent when word-wrapping.
+const unsigned WordWrapIndentation = 6;
+
+TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
+                                             const DiagnosticOptions &diags,
+                                             bool _OwnsOutputStream)
+  : OS(os), LangOpts(0), DiagOpts(&diags),
+    LastCaretDiagnosticWasNote(0),
+    OwnsOutputStream(_OwnsOutputStream) {
+}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter() {
+  if (OwnsOutputStream)
+    delete &OS;
+}
+
+void TextDiagnosticPrinter::
+PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
+  if (Loc.isInvalid()) return;
+
+  PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+
+  // Print out the other include frames first.
+  PrintIncludeStack(PLoc.getIncludeLoc(), SM);
+
+  if (DiagOpts->ShowLocation)
+    OS << "In file included from " << PLoc.getFilename()
+       << ':' << PLoc.getLine() << ":\n";
+  else
+    OS << "In included file:\n";
+}
+
+/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
+/// any characters in LineNo that intersect the SourceRange.
+void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
+                                           const SourceManager &SM,
+                                           unsigned LineNo, FileID FID,
+                                           std::string &CaretLine,
+                                           const std::string &SourceLine) {
+  assert(CaretLine.size() == SourceLine.size() &&
+         "Expect a correspondence between source and caret line!");
+  if (!R.isValid()) return;
+
+  SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
+  SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+
+  // If the End location and the start location are the same and are a macro
+  // location, then the range was something that came from a macro expansion
+  // or _Pragma.  If this is an object-like macro, the best we can do is to
+  // highlight the range.  If this is a function-like macro, we'd also like to
+  // highlight the arguments.
+  if (Begin == End && R.getEnd().isMacroID())
+    End = SM.getInstantiationRange(R.getEnd()).second;
+
+  unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
+  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
+    return;  // No intersection.
+
+  unsigned EndLineNo = SM.getInstantiationLineNumber(End);
+  if (EndLineNo < LineNo || SM.getFileID(End) != FID)
+    return;  // No intersection.
+
+  // Compute the column number of the start.
+  unsigned StartColNo = 0;
+  if (StartLineNo == LineNo) {
+    StartColNo = SM.getInstantiationColumnNumber(Begin);
+    if (StartColNo) --StartColNo;  // Zero base the col #.
+  }
+
+  // Pick the first non-whitespace column.
+  while (StartColNo < SourceLine.size() &&
+         (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
+    ++StartColNo;
+
+  // Compute the column number of the end.
+  unsigned EndColNo = CaretLine.size();
+  if (EndLineNo == LineNo) {
+    EndColNo = SM.getInstantiationColumnNumber(End);
+    if (EndColNo) {
+      --EndColNo;  // Zero base the col #.
+
+      // Add in the length of the token, so that we cover multi-char tokens.
+      EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts);
+    } else {
+      EndColNo = CaretLine.size();
+    }
+  }
+
+  // Pick the last non-whitespace column.
+  if (EndColNo <= SourceLine.size())
+    while (EndColNo-1 &&
+           (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
+      --EndColNo;
+  else
+    EndColNo = SourceLine.size();
+
+  // Fill the range with ~'s.
+  assert(StartColNo <= EndColNo && "Invalid range!");
+  for (unsigned i = StartColNo; i < EndColNo; ++i)
+    CaretLine[i] = '~';
+}
+
+/// \brief When the source code line we want to print is too long for
+/// the terminal, select the "interesting" region.
+static void SelectInterestingSourceRegion(std::string &SourceLine,
+                                          std::string &CaretLine,
+                                          std::string &FixItInsertionLine,
+                                          unsigned EndOfCaretToken,
+                                          unsigned Columns) {
+  if (CaretLine.size() > SourceLine.size())
+    SourceLine.resize(CaretLine.size(), ' ');
+
+  // Find the slice that we need to display the full caret line
+  // correctly.
+  unsigned CaretStart = 0, CaretEnd = CaretLine.size();
+  for (; CaretStart != CaretEnd; ++CaretStart)
+    if (!isspace(CaretLine[CaretStart]))
+      break;
+
+  for (; CaretEnd != CaretStart; --CaretEnd)
+    if (!isspace(CaretLine[CaretEnd - 1]))
+      break;
+
+  // Make sure we don't chop the string shorter than the caret token
+  // itself.
+  if (CaretEnd < EndOfCaretToken)
+    CaretEnd = EndOfCaretToken;
+
+  // If we have a fix-it line, make sure the slice includes all of the
+  // fix-it information.
+  if (!FixItInsertionLine.empty()) {
+    unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
+    for (; FixItStart != FixItEnd; ++FixItStart)
+      if (!isspace(FixItInsertionLine[FixItStart]))
+        break;
+
+    for (; FixItEnd != FixItStart; --FixItEnd)
+      if (!isspace(FixItInsertionLine[FixItEnd - 1]))
+        break;
+
+    if (FixItStart < CaretStart)
+      CaretStart = FixItStart;
+    if (FixItEnd > CaretEnd)
+      CaretEnd = FixItEnd;
+  }
+
+  // CaretLine[CaretStart, CaretEnd) contains all of the interesting
+  // parts of the caret line. While this slice is smaller than the
+  // number of columns we have, try to grow the slice to encompass
+  // more context.
+
+  // If the end of the interesting region comes before we run out of
+  // space in the terminal, start at the beginning of the line.
+  if (Columns > 3 && CaretEnd < Columns - 3)
+    CaretStart = 0;
+
+  unsigned TargetColumns = Columns;
+  if (TargetColumns > 8)
+    TargetColumns -= 8; // Give us extra room for the ellipses.
+  unsigned SourceLength = SourceLine.size();
+  while ((CaretEnd - CaretStart) < TargetColumns) {
+    bool ExpandedRegion = false;
+    // Move the start of the interesting region left until we've
+    // pulled in something else interesting.
+    if (CaretStart == 1)
+      CaretStart = 0;
+    else if (CaretStart > 1) {
+      unsigned NewStart = CaretStart - 1;
+
+      // Skip over any whitespace we see here; we're looking for
+      // another bit of interesting text.
+      while (NewStart && isspace(SourceLine[NewStart]))
+        --NewStart;
+
+      // Skip over this bit of "interesting" text.
+      while (NewStart && !isspace(SourceLine[NewStart]))
+        --NewStart;
+
+      // Move up to the non-whitespace character we just saw.
+      if (NewStart)
+        ++NewStart;
+
+      // If we're still within our limit, update the starting
+      // position within the source/caret line.
+      if (CaretEnd - NewStart <= TargetColumns) {
+        CaretStart = NewStart;
+        ExpandedRegion = true;
+      }
+    }
+
+    // Move the end of the interesting region right until we've
+    // pulled in something else interesting.
+    if (CaretEnd != SourceLength) {
+      assert(CaretEnd < SourceLength && "Unexpected caret position!");
+      unsigned NewEnd = CaretEnd;
+
+      // Skip over any whitespace we see here; we're looking for
+      // another bit of interesting text.
+      while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1]))
+        ++NewEnd;
+
+      // Skip over this bit of "interesting" text.
+      while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1]))
+        ++NewEnd;
+
+      if (NewEnd - CaretStart <= TargetColumns) {
+        CaretEnd = NewEnd;
+        ExpandedRegion = true;
+      }
+    }
+
+    if (!ExpandedRegion)
+      break;
+  }
+
+  // [CaretStart, CaretEnd) is the slice we want. Update the various
+  // output lines to show only this slice, with two-space padding
+  // before the lines so that it looks nicer.
+  if (CaretEnd < SourceLine.size())
+    SourceLine.replace(CaretEnd, std::string::npos, "...");
+  if (CaretEnd < CaretLine.size())
+    CaretLine.erase(CaretEnd, std::string::npos);
+  if (FixItInsertionLine.size() > CaretEnd)
+    FixItInsertionLine.erase(CaretEnd, std::string::npos);
+
+  if (CaretStart > 2) {
+    SourceLine.replace(0, CaretStart, "  ...");
+    CaretLine.replace(0, CaretStart, "     ");
+    if (FixItInsertionLine.size() >= CaretStart)
+      FixItInsertionLine.replace(0, CaretStart, "     ");
+  }
+}
+
+void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
+                                                SourceRange *Ranges,
+                                                unsigned NumRanges,
+                                                SourceManager &SM,
+                                          const CodeModificationHint *Hints,
+                                                unsigned NumHints,
+                                                unsigned Columns) {
+  assert(LangOpts && "Unexpected diagnostic outside source file processing");
+  assert(!Loc.isInvalid() && "must have a valid source location here");
+
+  // If this is a macro ID, first emit information about where this was
+  // instantiated (recursively) then emit information about where the token was
+  // spelled from.
+  if (!Loc.isFileID()) {
+    SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
+    // FIXME: Map ranges?
+    EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns);
+
+    // Map the location.
+    Loc = SM.getImmediateSpellingLoc(Loc);
+
+    // Map the ranges.
+    for (unsigned i = 0; i != NumRanges; ++i) {
+      SourceLocation S = Ranges[i].getBegin(), E = Ranges[i].getEnd();
+      if (S.isMacroID()) S = SM.getImmediateSpellingLoc(S);
+      if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E);
+      Ranges[i] = SourceRange(S, E);
+    }
+    
+    // Get the pretty name, according to #line directives etc.
+    PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+    
+    // If this diagnostic is not in the main file, print out the "included from"
+    // lines.
+    if (LastWarningLoc != PLoc.getIncludeLoc()) {
+      LastWarningLoc = PLoc.getIncludeLoc();
+      PrintIncludeStack(LastWarningLoc, SM);
+    }
+
+    if (DiagOpts->ShowLocation) {
+      // Emit the file/line/column that this expansion came from.
+      OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
+      if (DiagOpts->ShowColumn)
+        OS << PLoc.getColumn() << ':';
+      OS << ' ';
+    }
+    OS << "note: instantiated from:\n";
+
+    EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns);
+    return;
+  }
+
+  // Decompose the location into a FID/Offset pair.
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+  FileID FID = LocInfo.first;
+  unsigned FileOffset = LocInfo.second;
+
+  // Get information about the buffer it points into.
+  std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID);
+  const char *BufStart = BufferInfo.first;
+
+  unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
+  unsigned CaretEndColNo
+    = ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts);
+
+  // Rewind from the current position to the start of the line.
+  const char *TokPtr = BufStart+FileOffset;
+  const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
+
+
+  // Compute the line end.  Scan forward from the error position to the end of
+  // the line.
+  const char *LineEnd = TokPtr;
+  while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
+    ++LineEnd;
+
+  // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
+  // the source line length as currently being computed. See
+  // test/Misc/message-length.c.
+  CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
+
+  // Copy the line of code into an std::string for ease of manipulation.
+  std::string SourceLine(LineStart, LineEnd);
+
+  // Create a line for the caret that is filled with spaces that is the same
+  // length as the line of source code.
+  std::string CaretLine(LineEnd-LineStart, ' ');
+
+  // Highlight all of the characters covered by Ranges with ~ characters.
+  if (NumRanges) {
+    unsigned LineNo = SM.getLineNumber(FID, FileOffset);
+
+    for (unsigned i = 0, e = NumRanges; i != e; ++i)
+      HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine);
+  }
+
+  // Next, insert the caret itself.
+  if (ColNo-1 < CaretLine.size())
+    CaretLine[ColNo-1] = '^';
+  else
+    CaretLine.push_back('^');
+
+  // Scan the source line, looking for tabs.  If we find any, manually expand
+  // them to spaces and update the CaretLine to match.
+  for (unsigned i = 0; i != SourceLine.size(); ++i) {
+    if (SourceLine[i] != '\t') continue;
+
+    // Replace this tab with at least one space.
+    SourceLine[i] = ' ';
+
+    // Compute the number of spaces we need to insert.
+    unsigned TabStop = DiagOpts->TabStop;
+    assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
+           "Invalid -ftabstop value");
+    unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1);
+    assert(NumSpaces < TabStop && "Invalid computation of space amt");
+
+    // Insert spaces into the SourceLine.
+    SourceLine.insert(i+1, NumSpaces, ' ');
+
+    // Insert spaces or ~'s into CaretLine.
+    CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
+  }
+
+  // If we are in -fdiagnostics-print-source-range-info mode, we are trying to
+  // produce easily machine parsable output.  Add a space before the source line
+  // and the caret to make it trivial to tell the main diagnostic line from what
+  // the user is intended to see.
+  if (DiagOpts->ShowSourceRanges) {
+    SourceLine = ' ' + SourceLine;
+    CaretLine = ' ' + CaretLine;
+  }
+
+  std::string FixItInsertionLine;
+  if (NumHints && DiagOpts->ShowFixits) {
+    for (const CodeModificationHint *Hint = Hints, *LastHint = Hints + NumHints;
+         Hint != LastHint; ++Hint) {
+      if (Hint->InsertionLoc.isValid()) {
+        // We have an insertion hint. Determine whether the inserted
+        // code is on the same line as the caret.
+        std::pair<FileID, unsigned> HintLocInfo
+          = SM.getDecomposedInstantiationLoc(Hint->InsertionLoc);
+        if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) ==
+              SM.getLineNumber(FID, FileOffset)) {
+          // Insert the new code into the line just below the code
+          // that the user wrote.
+          unsigned HintColNo
+            = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second);
+          unsigned LastColumnModified
+            = HintColNo - 1 + Hint->CodeToInsert.size();
+          if (LastColumnModified > FixItInsertionLine.size())
+            FixItInsertionLine.resize(LastColumnModified, ' ');
+          std::copy(Hint->CodeToInsert.begin(), Hint->CodeToInsert.end(),
+                    FixItInsertionLine.begin() + HintColNo - 1);
+        } else {
+          FixItInsertionLine.clear();
+          break;
+        }
+      }
+    }
+    // Now that we have the entire fixit line, expand the tabs in it.
+    // Since we don't want to insert spaces in the middle of a word,
+    // find each word and the column it should line up with and insert
+    // spaces until they match.
+    if (!FixItInsertionLine.empty()) {
+      unsigned FixItPos = 0;
+      unsigned LinePos = 0;
+      unsigned TabExpandedCol = 0;
+      unsigned LineLength = LineEnd - LineStart;
+
+      while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) {
+        // Find the next word in the FixIt line.
+        while (FixItPos < FixItInsertionLine.size() &&
+               FixItInsertionLine[FixItPos] == ' ')
+          ++FixItPos;
+        unsigned CharDistance = FixItPos - TabExpandedCol;
+
+        // Walk forward in the source line, keeping track of
+        // the tab-expanded column.
+        for (unsigned I = 0; I < CharDistance; ++I, ++LinePos)
+          if (LinePos >= LineLength || LineStart[LinePos] != '\t')
+            ++TabExpandedCol;
+          else
+            TabExpandedCol =
+              (TabExpandedCol/DiagOpts->TabStop + 1) * DiagOpts->TabStop;
+
+        // Adjust the fixit line to match this column.
+        FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' ');
+        FixItPos = TabExpandedCol;
+
+        // Walk to the end of the word.
+        while (FixItPos < FixItInsertionLine.size() &&
+               FixItInsertionLine[FixItPos] != ' ')
+          ++FixItPos;
+      }
+    }
+  }
+
+  // If the source line is too long for our terminal, select only the
+  // "interesting" source region within that line.
+  if (Columns && SourceLine.size() > Columns)
+    SelectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
+                                  CaretEndColNo, Columns);
+
+  // Finally, remove any blank spaces from the end of CaretLine.
+  while (CaretLine[CaretLine.size()-1] == ' ')
+    CaretLine.erase(CaretLine.end()-1);
+
+  // Emit what we have computed.
+  OS << SourceLine << '\n';
+
+  if (DiagOpts->ShowColors)
+    OS.changeColor(caretColor, true);
+  OS << CaretLine << '\n';
+  if (DiagOpts->ShowColors)
+    OS.resetColor();
+
+  if (!FixItInsertionLine.empty()) {
+    if (DiagOpts->ShowColors)
+      // Print fixit line in color
+      OS.changeColor(fixitColor, false);
+    if (DiagOpts->ShowSourceRanges)
+      OS << ' ';
+    OS << FixItInsertionLine << '\n';
+    if (DiagOpts->ShowColors)
+      OS.resetColor();
+  }
+}
+
+/// \brief Skip over whitespace in the string, starting at the given
+/// index.
+///
+/// \returns The index of the first non-whitespace character that is
+/// greater than or equal to Idx or, if no such character exists,
+/// returns the end of the string.
+static unsigned skipWhitespace(unsigned Idx,
+                               const llvm::SmallVectorImpl<char> &Str,
+                               unsigned Length) {
+  while (Idx < Length && isspace(Str[Idx]))
+    ++Idx;
+  return Idx;
+}
+
+/// \brief If the given character is the start of some kind of
+/// balanced punctuation (e.g., quotes or parentheses), return the
+/// character that will terminate the punctuation.
+///
+/// \returns The ending punctuation character, if any, or the NULL
+/// character if the input character does not start any punctuation.
+static inline char findMatchingPunctuation(char c) {
+  switch (c) {
+  case '\'': return '\'';
+  case '`': return '\'';
+  case '"':  return '"';
+  case '(':  return ')';
+  case '[': return ']';
+  case '{': return '}';
+  default: break;
+  }
+
+  return 0;
+}
+
+/// \brief Find the end of the word starting at the given offset
+/// within a string.
+///
+/// \returns the index pointing one character past the end of the
+/// word.
+static unsigned findEndOfWord(unsigned Start,
+                              const llvm::SmallVectorImpl<char> &Str,
+                              unsigned Length, unsigned Column,
+                              unsigned Columns) {
+  assert(Start < Str.size() && "Invalid start position!");
+  unsigned End = Start + 1;
+
+  // If we are already at the end of the string, take that as the word.
+  if (End == Str.size())
+    return End;
+
+  // Determine if the start of the string is actually opening
+  // punctuation, e.g., a quote or parentheses.
+  char EndPunct = findMatchingPunctuation(Str[Start]);
+  if (!EndPunct) {
+    // This is a normal word. Just find the first space character.
+    while (End < Length && !isspace(Str[End]))
+      ++End;
+    return End;
+  }
+
+  // We have the start of a balanced punctuation sequence (quotes,
+  // parentheses, etc.). Determine the full sequence is.
+  llvm::SmallVector<char, 16> PunctuationEndStack;
+  PunctuationEndStack.push_back(EndPunct);
+  while (End < Length && !PunctuationEndStack.empty()) {
+    if (Str[End] == PunctuationEndStack.back())
+      PunctuationEndStack.pop_back();
+    else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
+      PunctuationEndStack.push_back(SubEndPunct);
+
+    ++End;
+  }
+
+  // Find the first space character after the punctuation ended.
+  while (End < Length && !isspace(Str[End]))
+    ++End;
+
+  unsigned PunctWordLength = End - Start;
+  if (// If the word fits on this line
+      Column + PunctWordLength <= Columns ||
+      // ... or the word is "short enough" to take up the next line
+      // without too much ugly white space
+      PunctWordLength < Columns/3)
+    return End; // Take the whole thing as a single "word".
+
+  // The whole quoted/parenthesized string is too long to print as a
+  // single "word". Instead, find the "word" that starts just after
+  // the punctuation and use that end-point instead. This will recurse
+  // until it finds something small enough to consider a word.
+  return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
+}
+
+/// \brief Print the given string to a stream, word-wrapping it to
+/// some number of columns in the process.
+///
+/// \brief OS the stream to which the word-wrapping string will be
+/// emitted.
+///
+/// \brief Str the string to word-wrap and output.
+///
+/// \brief Columns the number of columns to word-wrap to.
+///
+/// \brief Column the column number at which the first character of \p
+/// Str will be printed. This will be non-zero when part of the first
+/// line has already been printed.
+///
+/// \brief Indentation the number of spaces to indent any lines beyond
+/// the first line.
+///
+/// \returns true if word-wrapping was required, or false if the
+/// string fit on the first line.
+static bool PrintWordWrapped(llvm::raw_ostream &OS,
+                             const llvm::SmallVectorImpl<char> &Str,
+                             unsigned Columns,
+                             unsigned Column = 0,
+                             unsigned Indentation = WordWrapIndentation) {
+  unsigned Length = Str.size();
+
+  // If there is a newline in this message somewhere, find that
+  // newline and split the message into the part before the newline
+  // (which will be word-wrapped) and the part from the newline one
+  // (which will be emitted unchanged).
+  for (unsigned I = 0; I != Length; ++I)
+    if (Str[I] == '\n') {
+      Length = I;
+      break;
+    }
+
+  // The string used to indent each line.
+  llvm::SmallString<16> IndentStr;
+  IndentStr.assign(Indentation, ' ');
+  bool Wrapped = false;
+  for (unsigned WordStart = 0, WordEnd; WordStart < Length;
+       WordStart = WordEnd) {
+    // Find the beginning of the next word.
+    WordStart = skipWhitespace(WordStart, Str, Length);
+    if (WordStart == Length)
+      break;
+
+    // Find the end of this word.
+    WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
+
+    // Does this word fit on the current line?
+    unsigned WordLength = WordEnd - WordStart;
+    if (Column + WordLength < Columns) {
+      // This word fits on the current line; print it there.
+      if (WordStart) {
+        OS << ' ';
+        Column += 1;
+      }
+      OS.write(&Str[WordStart], WordLength);
+      Column += WordLength;
+      continue;
+    }
+
+    // This word does not fit on the current line, so wrap to the next
+    // line.
+    OS << '\n';
+    OS.write(&IndentStr[0], Indentation);
+    OS.write(&Str[WordStart], WordLength);
+    Column = Indentation + WordLength;
+    Wrapped = true;
+  }
+
+  if (Length == Str.size())
+    return Wrapped; // We're done.
+
+  // There is a newline in the message, followed by something that
+  // will not be word-wrapped. Print that.
+  OS.write(&Str[Length], Str.size() - Length);
+  return true;
+}
+
+void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
+                                             const DiagnosticInfo &Info) {
+  // Keeps track of the the starting position of the location
+  // information (e.g., "foo.c:10:4:") that precedes the error
+  // message. We use this information to determine how long the
+  // file+line+column number prefix is.
+  uint64_t StartOfLocationInfo = OS.tell();
+
+  // If the location is specified, print out a file/line/col and include trace
+  // if enabled.
+  if (Info.getLocation().isValid()) {
+    const SourceManager &SM = Info.getLocation().getManager();
+    PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
+    unsigned LineNo = PLoc.getLine();
+
+    // First, if this diagnostic is not in the main file, print out the
+    // "included from" lines.
+    if (LastWarningLoc != PLoc.getIncludeLoc()) {
+      LastWarningLoc = PLoc.getIncludeLoc();
+      PrintIncludeStack(LastWarningLoc, SM);
+      StartOfLocationInfo = OS.tell();
+    }
+
+    // Compute the column number.
+    if (DiagOpts->ShowLocation) {
+      if (DiagOpts->ShowColors)
+        OS.changeColor(savedColor, true);
+      
+      // Emit a Visual Studio compatible line number syntax.
+      if (LangOpts && LangOpts->Microsoft) {
+        OS << PLoc.getFilename() << '(' << LineNo << ')';
+        OS << " : ";
+      } else {
+        OS << PLoc.getFilename() << ':' << LineNo << ':';
+        if (DiagOpts->ShowColumn)
+          if (unsigned ColNo = PLoc.getColumn())
+            OS << ColNo << ':';
+      }
+      if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
+        FileID CaretFileID =
+          SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
+        bool PrintedRange = false;
+
+        for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) {
+          // Ignore invalid ranges.
+          if (!Info.getRange(i).isValid()) continue;
+
+          SourceLocation B = Info.getRange(i).getBegin();
+          SourceLocation E = Info.getRange(i).getEnd();
+          B = SM.getInstantiationLoc(B);
+          E = SM.getInstantiationLoc(E);
+
+          // If the End location and the start location are the same and are a
+          // macro location, then the range was something that came from a macro
+          // expansion or _Pragma.  If this is an object-like macro, the best we
+          // can do is to highlight the range.  If this is a function-like
+          // macro, we'd also like to highlight the arguments.
+          if (B == E && Info.getRange(i).getEnd().isMacroID())
+            E = SM.getInstantiationRange(Info.getRange(i).getEnd()).second;
+
+          std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
+          std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
+
+          // If the start or end of the range is in another file, just discard
+          // it.
+          if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
+            continue;
+
+          // Add in the length of the token, so that we cover multi-char tokens.
+          unsigned TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts);
+
+          OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
+             << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
+             << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
+             << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) << '}';
+          PrintedRange = true;
+        }
+
+        if (PrintedRange)
+          OS << ':';
+      }
+      OS << ' ';
+      if (DiagOpts->ShowColors)
+        OS.resetColor();
+    }
+  }
+
+  if (DiagOpts->ShowColors) {
+    // Print diagnostic category in bold and color
+    switch (Level) {
+    case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
+    case Diagnostic::Note:    OS.changeColor(noteColor, true); break;
+    case Diagnostic::Warning: OS.changeColor(warningColor, true); break;
+    case Diagnostic::Error:   OS.changeColor(errorColor, true); break;
+    case Diagnostic::Fatal:   OS.changeColor(fatalColor, true); break;
+    }
+  }
+
+  switch (Level) {
+  case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
+  case Diagnostic::Note:    OS << "note: "; break;
+  case Diagnostic::Warning: OS << "warning: "; break;
+  case Diagnostic::Error:   OS << "error: "; break;
+  case Diagnostic::Fatal:   OS << "fatal error: "; break;
+  }
+
+  if (DiagOpts->ShowColors)
+    OS.resetColor();
+
+  llvm::SmallString<100> OutStr;
+  Info.FormatDiagnostic(OutStr);
+
+  if (DiagOpts->ShowOptionNames)
+    if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
+      OutStr += " [-W";
+      OutStr += Opt;
+      OutStr += ']';
+    }
+
+  if (DiagOpts->ShowColors) {
+    // Print warnings, errors and fatal errors in bold, no color
+    switch (Level) {
+    case Diagnostic::Warning: OS.changeColor(savedColor, true); break;
+    case Diagnostic::Error:   OS.changeColor(savedColor, true); break;
+    case Diagnostic::Fatal:   OS.changeColor(savedColor, true); break;
+    default: break; //don't bold notes
+    }
+  }
+
+  if (DiagOpts->MessageLength) {
+    // We will be word-wrapping the error message, so compute the
+    // column number where we currently are (after printing the
+    // location information).
+    unsigned Column = OS.tell() - StartOfLocationInfo;
+    PrintWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column);
+  } else {
+    OS.write(OutStr.begin(), OutStr.size());
+  }
+  OS << '\n';
+  if (DiagOpts->ShowColors)
+    OS.resetColor();
+
+  // If caret diagnostics are enabled and we have location, we want to
+  // emit the caret.  However, we only do this if the location moved
+  // from the last diagnostic, if the last diagnostic was a note that
+  // was part of a different warning or error diagnostic, or if the
+  // diagnostic has ranges.  We don't want to emit the same caret
+  // multiple times if one loc has multiple diagnostics.
+  if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
+      ((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
+       (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
+       Info.getNumCodeModificationHints())) {
+    // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
+    LastLoc = Info.getLocation();
+    LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
+
+    // Get the ranges into a local array we can hack on.
+    SourceRange Ranges[20];
+    unsigned NumRanges = Info.getNumRanges();
+    assert(NumRanges < 20 && "Out of space");
+    for (unsigned i = 0; i != NumRanges; ++i)
+      Ranges[i] = Info.getRange(i);
+
+    unsigned NumHints = Info.getNumCodeModificationHints();
+    for (unsigned idx = 0; idx < NumHints; ++idx) {
+      const CodeModificationHint &Hint = Info.getCodeModificationHint(idx);
+      if (Hint.RemoveRange.isValid()) {
+        assert(NumRanges < 20 && "Out of space");
+        Ranges[NumRanges++] = Hint.RemoveRange;
+      }
+    }
+
+    EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
+                        Info.getCodeModificationHints(),
+                        Info.getNumCodeModificationHints(),
+                        DiagOpts->MessageLength);
+  }
+
+  OS.flush();
+}
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
new file mode 100644
index 0000000..be9db42
--- /dev/null
+++ b/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,119 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+  namespace XML {
+    namespace {
+
+//---------------------------------------------------------
+class TypeWriter : public TypeVisitor<TypeWriter> {
+  DocumentXML& Doc;
+
+public:
+  TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* T) {          \
+    Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML                // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME )       Doc.addAttribute(NAME, T->FN);
+#define TYPE_ATTRIBUTE_XML( FN )        ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN )     ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME )   Doc.addAttributeOptional(NAME, T->FN);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = false;             \
+    switch (T->FN) {                    \
+    default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = true;              \
+    switch (T->FN) {                    \
+    default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME )         case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML                    } }
+#define END_NODE_XML                    }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//---------------------------------------------------------
+    } // anon clang
+  } // NS XML
+
+//---------------------------------------------------------
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder> {
+  DocumentXML& Doc;
+
+  void addIfType(const Type* pType) {
+    Doc.addTypeRecursively(pType);
+  }
+
+  void addIfType(const QualType& pType) {
+    Doc.addTypeRecursively(pType);
+  }
+
+  template<class T> void addIfType(T) {}
+
+public:
+  TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* T)            \
+  {
+
+#define ID_ATTRIBUTE_XML
+#define TYPE_ATTRIBUTE_XML( FN )        Doc.addTypeRecursively(T->FN);
+#define CONTEXT_ATTRIBUTE_XML( FN )
+#define ATTRIBUTE_XML( FN, NAME )       addIfType(T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )
+#define ENUM_XML( VALUE, NAME )
+#define END_ENUM_XML
+#define END_NODE_XML                    }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//---------------------------------------------------------
+void DocumentXML::addParentTypes(const Type* pType) {
+  TypeAdder(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const Type* pType) {
+  XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const QualType& pType) {
+  XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp
new file mode 100644
index 0000000..99ec910
--- /dev/null
+++ b/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -0,0 +1,346 @@
+//===--- VerifyDiagnosticsClient.cpp - Verifying Diagnostic Client --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+VerifyDiagnosticsClient::VerifyDiagnosticsClient(Diagnostic &_Diags,
+                                                 DiagnosticClient *_Primary)
+  : Diags(_Diags), PrimaryClient(_Primary),
+    Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0), NumErrors(0) {
+}
+
+VerifyDiagnosticsClient::~VerifyDiagnosticsClient() {
+  CheckDiagnostics();
+}
+
+// DiagnosticClient interface.
+
+void VerifyDiagnosticsClient::BeginSourceFile(const LangOptions &LangOpts,
+                                             const Preprocessor *PP) {
+  // FIXME: Const hack, we screw up the preprocessor but in practice its ok
+  // because it doesn't get reused. It would be better if we could make a copy
+  // though.
+  CurrentPreprocessor = const_cast<Preprocessor*>(PP);
+
+  PrimaryClient->BeginSourceFile(LangOpts, PP);
+}
+
+void VerifyDiagnosticsClient::EndSourceFile() {
+  CheckDiagnostics();
+
+  PrimaryClient->EndSourceFile();
+
+  CurrentPreprocessor = 0;
+}
+
+void VerifyDiagnosticsClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                              const DiagnosticInfo &Info) {
+  // Send the diagnostic to the buffer, we will check it once we reach the end
+  // of the source file (or are destructed).
+  Buffer->HandleDiagnostic(DiagLevel, Info);
+}
+
+// FIXME: It would be nice to just get this from the primary diagnostic client
+// or something.
+bool VerifyDiagnosticsClient::HadErrors() {
+  CheckDiagnostics();
+
+  return NumErrors != 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Checking diagnostics implementation.
+//===----------------------------------------------------------------------===//
+
+typedef TextDiagnosticBuffer::DiagList DiagList;
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+/// FindDiagnostics - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in a diagnostic list.
+///
+static void FindDiagnostics(const char *CommentStart, unsigned CommentLen,
+                            DiagList &ExpectedDiags,
+                            Preprocessor &PP, SourceLocation Pos,
+                            const char *ExpectedStr) {
+  const char *CommentEnd = CommentStart+CommentLen;
+  unsigned ExpectedStrLen = strlen(ExpectedStr);
+
+  // Find all expected-foo diagnostics in the string and add them to
+  // ExpectedDiags.
+  while (CommentStart != CommentEnd) {
+    CommentStart = std::find(CommentStart, CommentEnd, 'e');
+    if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return;
+
+    // If this isn't expected-foo, ignore it.
+    if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) {
+      ++CommentStart;
+      continue;
+    }
+
+    CommentStart += ExpectedStrLen;
+
+    // Skip whitespace.
+    while (CommentStart != CommentEnd &&
+           isspace(CommentStart[0]))
+      ++CommentStart;
+
+    // Default, if we find the '{' now, is 1 time.
+    int Times = 1;
+    int Temp = 0;
+    // In extended syntax, there could be a digit now.
+    while (CommentStart != CommentEnd &&
+           CommentStart[0] >= '0' && CommentStart[0] <= '9') {
+      Temp *= 10;
+      Temp += CommentStart[0] - '0';
+      ++CommentStart;
+    }
+    if (Temp > 0)
+      Times = Temp;
+
+    // Skip whitespace again.
+    while (CommentStart != CommentEnd &&
+           isspace(CommentStart[0]))
+      ++CommentStart;
+
+    // We should have a {{ now.
+    if (CommentEnd-CommentStart < 2 ||
+        CommentStart[0] != '{' || CommentStart[1] != '{') {
+      if (std::find(CommentStart, CommentEnd, '{') != CommentEnd)
+        PP.Diag(Pos, diag::err_verify_bogus_characters);
+      else
+        PP.Diag(Pos, diag::err_verify_missing_start);
+      return;
+    }
+    CommentStart += 2;
+
+    // Find the }}.
+    const char *ExpectedEnd = CommentStart;
+    while (1) {
+      ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}');
+      if (CommentEnd-ExpectedEnd < 2) {
+        PP.Diag(Pos, diag::err_verify_missing_end);
+        return;
+      }
+
+      if (ExpectedEnd[1] == '}')
+        break;
+
+      ++ExpectedEnd;  // Skip over singular }'s
+    }
+
+    std::string Msg(CommentStart, ExpectedEnd);
+    std::string::size_type FindPos;
+    while ((FindPos = Msg.find("\\n")) != std::string::npos)
+      Msg.replace(FindPos, 2, "\n");
+    // Add is possibly multiple times.
+    for (int i = 0; i < Times; ++i)
+      ExpectedDiags.push_back(std::make_pair(Pos, Msg));
+
+    CommentStart = ExpectedEnd;
+  }
+}
+
+/// FindExpectedDiags - Lex the main source file to find all of the
+//   expected errors and warnings.
+static void FindExpectedDiags(Preprocessor &PP,
+                              DiagList &ExpectedErrors,
+                              DiagList &ExpectedWarnings,
+                              DiagList &ExpectedNotes) {
+  // Create a raw lexer to pull all the comments out of the main file.  We don't
+  // want to look in #include'd headers for expected-error strings.
+  SourceManager &SM = PP.getSourceManager();
+  FileID FID = SM.getMainFileID();
+  if (SM.getMainFileID().isInvalid())
+    return;
+
+  // Create a lexer to lex all the tokens of the main file in raw mode.
+  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+  Lexer RawLex(FID, FromFile, SM, PP.getLangOptions());
+
+  // Return comments as tokens, this is how we find expected diagnostics.
+  RawLex.SetCommentRetentionState(true);
+
+  Token Tok;
+  Tok.setKind(tok::comment);
+  while (Tok.isNot(tok::eof)) {
+    RawLex.Lex(Tok);
+    if (!Tok.is(tok::comment)) continue;
+
+    std::string Comment = PP.getSpelling(Tok);
+    if (Comment.empty()) continue;
+
+    // Find all expected errors.
+    FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP,
+                    Tok.getLocation(), "expected-error");
+
+    // Find all expected warnings.
+    FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP,
+                    Tok.getLocation(), "expected-warning");
+
+    // Find all expected notes.
+    FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP,
+                    Tok.getLocation(), "expected-note");
+  };
+}
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+///
+static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
+                             const_diag_iterator diag_begin,
+                             const_diag_iterator diag_end,
+                             const char *Kind, bool Expected) {
+  if (diag_begin == diag_end) return 0;
+
+  llvm::SmallString<256> Fmt;
+  llvm::raw_svector_ostream OS(Fmt);
+  for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
+    if (I->first.isInvalid() || !SourceMgr)
+      OS << "\n  (frontend)";
+    else
+      OS << "\n  Line " << SourceMgr->getInstantiationLineNumber(I->first);
+    OS << ": " << I->second;
+  }
+
+  Diags.Report(diag::err_verify_inconsistent_diags)
+    << Kind << !Expected << OS.str();
+  return std::distance(diag_begin, diag_end);
+}
+
+/// CompareDiagLists - Compare two diagnostic lists and return the difference
+/// between them.
+///
+static unsigned CompareDiagLists(Diagnostic &Diags,
+                                 SourceManager &SourceMgr,
+                                 const_diag_iterator d1_begin,
+                                 const_diag_iterator d1_end,
+                                 const_diag_iterator d2_begin,
+                                 const_diag_iterator d2_end,
+                                 const char *Label) {
+  DiagList LeftOnly;
+  DiagList Left(d1_begin, d1_end);
+  DiagList Right(d2_begin, d2_end);
+
+  for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
+    unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first);
+    const std::string &Diag1 = I->second;
+
+    DiagList::iterator II, IE;
+    for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
+      unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+      if (LineNo1 != LineNo2) continue;
+
+      const std::string &Diag2 = II->second;
+      if (Diag2.find(Diag1) != std::string::npos ||
+          Diag1.find(Diag2) != std::string::npos) {
+        break;
+      }
+    }
+    if (II == IE) {
+      // Not found.
+      LeftOnly.push_back(*I);
+    } else {
+      // Found. The same cannot be found twice.
+      Right.erase(II);
+    }
+  }
+  // Now all that's left in Right are those that were not matched.
+
+  return (PrintProblem(Diags, &SourceMgr,
+                      LeftOnly.begin(), LeftOnly.end(), Label, true) +
+          PrintProblem(Diags, &SourceMgr,
+                       Right.begin(), Right.end(), Label, false));
+}
+
+/// CheckResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+///
+static unsigned CheckResults(Diagnostic &Diags, SourceManager &SourceMgr,
+                             const TextDiagnosticBuffer &Buffer,
+                             const DiagList &ExpectedErrors,
+                             const DiagList &ExpectedWarnings,
+                             const DiagList &ExpectedNotes) {
+  // We want to capture the delta between what was expected and what was
+  // seen.
+  //
+  //   Expected \ Seen - set expected but not seen
+  //   Seen \ Expected - set seen but not expected
+  unsigned NumProblems = 0;
+
+  // See if there are error mismatches.
+  NumProblems += CompareDiagLists(Diags, SourceMgr,
+                                  ExpectedErrors.begin(), ExpectedErrors.end(),
+                                  Buffer.err_begin(), Buffer.err_end(),
+                                  "error");
+
+  // See if there are warning mismatches.
+  NumProblems += CompareDiagLists(Diags, SourceMgr,
+                                  ExpectedWarnings.begin(),
+                                  ExpectedWarnings.end(),
+                                  Buffer.warn_begin(), Buffer.warn_end(),
+                                  "warning");
+
+  // See if there are note mismatches.
+  NumProblems += CompareDiagLists(Diags, SourceMgr,
+                                  ExpectedNotes.begin(),
+                                  ExpectedNotes.end(),
+                                  Buffer.note_begin(), Buffer.note_end(),
+                                  "note");
+
+  return NumProblems;
+}
+
+
+void VerifyDiagnosticsClient::CheckDiagnostics() {
+  DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes;
+
+  // Ensure any diagnostics go to the primary client.
+  DiagnosticClient *CurClient = Diags.getClient();
+  Diags.setClient(PrimaryClient.get());
+
+  // If we have a preprocessor, scan the source for expected diagnostic
+  // markers. If not then any diagnostics are unexpected.
+  if (CurrentPreprocessor) {
+    FindExpectedDiags(*CurrentPreprocessor, ExpectedErrors, ExpectedWarnings,
+                      ExpectedNotes);
+
+    // Check that the expected diagnostics occurred.
+    NumErrors += CheckResults(Diags, CurrentPreprocessor->getSourceManager(),
+                              *Buffer,
+                              ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+  } else {
+    NumErrors += (PrintProblem(Diags, 0,
+                               Buffer->err_begin(), Buffer->err_end(),
+                               "error", false) +
+                  PrintProblem(Diags, 0,
+                               Buffer->warn_begin(), Buffer->warn_end(),
+                               "warn", false) +
+                  PrintProblem(Diags, 0,
+                               Buffer->note_begin(), Buffer->note_end(),
+                               "note", false));
+  }
+
+  Diags.setClient(CurClient);
+
+  // Reset the buffer, we have processed all the diagnostics in it.
+  Buffer.reset(new TextDiagnosticBuffer());
+}
diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp
new file mode 100644
index 0000000..4bf507d
--- /dev/null
+++ b/lib/Frontend/Warnings.cpp
@@ -0,0 +1,127 @@
+//===--- Warnings.cpp - C-Language Front-end ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line warning options handler.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is responsible for handling all warning options. This includes
+// a number of -Wfoo options and their variants, which are driven by TableGen-
+// generated data, and the special cases -pedantic, -pedantic-errors, -w,
+// -Werror and -Wfatal-errors.
+//
+// Each warning option controls any number of actual warnings.
+// Given a warning option 'foo', the following are valid:
+//    -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo
+//
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include <cstring>
+#include <utility>
+#include <algorithm>
+using namespace clang;
+
+bool clang::ProcessWarningOptions(Diagnostic &Diags,
+                                  const DiagnosticOptions &Opts) {
+  Diags.setSuppressSystemWarnings(true);  // Default to -Wno-system-headers
+  Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
+
+  // If -pedantic or -pedantic-errors was specified, then we want to map all
+  // extension diagnostics onto WARNING or ERROR unless the user has futz'd
+  // around with them explicitly.
+  if (Opts.PedanticErrors)
+    Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Error);
+  else if (Opts.Pedantic)
+    Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Warn);
+  else
+    Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Ignore);
+
+  for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
+    const std::string &Opt = Opts.Warnings[i];
+    const char *OptStart = &Opt[0];
+    const char *OptEnd = OptStart+Opt.size();
+    assert(*OptEnd == 0 && "Expect null termination for lower-bound search");
+
+    // Check to see if this warning starts with "no-", if so, this is a negative
+    // form of the option.
+    bool isPositive = true;
+    if (OptEnd-OptStart > 3 && memcmp(OptStart, "no-", 3) == 0) {
+      isPositive = false;
+      OptStart += 3;
+    }
+
+    // Figure out how this option affects the warning.  If -Wfoo, map the
+    // diagnostic to a warning, if -Wno-foo, map it to ignore.
+    diag::Mapping Mapping = isPositive ? diag::MAP_WARNING : diag::MAP_IGNORE;
+
+    // -Wsystem-headers is a special case, not driven by the option table.  It
+    // cannot be controlled with -Werror.
+    if (OptEnd-OptStart == 14 && memcmp(OptStart, "system-headers", 14) == 0) {
+      Diags.setSuppressSystemWarnings(!isPositive);
+      continue;
+    }
+
+    // -Werror/-Wno-error is a special case, not controlled by the option table.
+    // It also has the "specifier" form of -Werror=foo and -Werror-foo.
+    if (OptEnd-OptStart >= 5 && memcmp(OptStart, "error", 5) == 0) {
+      const char *Specifier = 0;
+      if (OptEnd-OptStart != 5) {  // Specifier must be present.
+        if ((OptStart[5] != '=' && OptStart[5] != '-') ||
+            OptEnd-OptStart == 6) {
+          Diags.Report(diag::warn_unknown_warning_specifier)
+            << "-Werror" << ("-W" + Opt);
+          continue;
+        }
+        Specifier = OptStart+6;
+      }
+
+      if (Specifier == 0) {
+        Diags.setWarningsAsErrors(isPositive);
+        continue;
+      }
+
+      // -Werror=foo maps foo to Error, -Wno-error=foo maps it to Warning.
+      Mapping = isPositive ? diag::MAP_ERROR : diag::MAP_WARNING_NO_WERROR;
+      OptStart = Specifier;
+    }
+
+    // -Wfatal-errors is yet another special case.
+    if (OptEnd-OptStart >= 12 && memcmp(OptStart, "fatal-errors", 12) == 0) {
+      const char* Specifier = 0;
+      if (OptEnd-OptStart != 12) {
+        if ((OptStart[12] != '=' && OptStart[12] != '-') ||
+            OptEnd-OptStart == 13) {
+          Diags.Report(diag::warn_unknown_warning_specifier)
+            << "-Wfatal-errors" << ("-W" + Opt);
+          continue;
+        }
+        Specifier = OptStart + 13;
+      }
+
+      if (Specifier == 0) {
+        Diags.setErrorsAsFatal(isPositive);
+        continue;
+      }
+
+      // -Wfatal-errors=foo maps foo to Fatal, -Wno-fatal-errors=foo
+      // maps it to Error.
+      Mapping = isPositive ? diag::MAP_FATAL : diag::MAP_ERROR_NO_WFATAL;
+      OptStart = Specifier;
+    }
+
+    if (Diags.setDiagnosticGroupMapping(OptStart, Mapping))
+      Diags.Report(diag::warn_unknown_warning_option) << ("-W" + Opt);
+  }
+
+  return false;
+}